* [-- 06/13] null: fake PMD capabilities
From: Michał Mirosław @ 2016-12-13 1:35 UTC (permalink / raw)
To: dev
In-Reply-To: <20161213012851.1F4A0388F@dpdk.org>
From: Paweł Małachowski <pawel.malachowski@atendesoftware.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/null/rte_eth_null.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 836d982..c802bc0 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -284,6 +284,9 @@ eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
return 0;
}
+static void
+eth_dev_void_ok(struct rte_eth_dev *dev __rte_unused) { return; }
+
static void
eth_dev_info(struct rte_eth_dev *dev,
@@ -304,6 +307,12 @@ eth_dev_info(struct rte_eth_dev *dev,
dev_info->pci_dev = NULL;
dev_info->reta_size = internals->reta_size;
dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
+ /* We hereby declare we can RX offload VLAN-s out of thin air and update
+ * checksums and VLANs before sinking packets in /dev/null
+ */
+ dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
+ dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+ DEV_TX_OFFLOAD_IPV4_CKSUM;
}
static void
@@ -477,7 +486,12 @@ static const struct eth_dev_ops ops = {
.reta_update = eth_rss_reta_update,
.reta_query = eth_rss_reta_query,
.rss_hash_update = eth_rss_hash_update,
- .rss_hash_conf_get = eth_rss_hash_conf_get
+ .rss_hash_conf_get = eth_rss_hash_conf_get,
+ /* Fake our capabilities */
+ .promiscuous_enable = eth_dev_void_ok,
+ .promiscuous_disable = eth_dev_void_ok,
+ .allmulticast_enable = eth_dev_void_ok,
+ .allmulticast_disable = eth_dev_void_ok
};
int
--
2.10.2
^ permalink raw reply related
* [PATCH v2 09/13] PMD/af_packet: guard against buffer overruns in TX path
From: Michał Mirosław @ 2016-12-13 1:28 UTC (permalink / raw)
To: dev
In-Reply-To: <20161213010927.9B12CFA30@dpdk.org>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/af_packet/rte_eth_af_packet.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index 5599e02..fc2dc4a 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -83,6 +83,7 @@ struct pkt_rx_queue {
struct pkt_tx_queue {
int sockfd;
+ unsigned int frame_data_size;
struct iovec *rd;
uint8_t *map;
@@ -206,13 +207,20 @@ eth_af_packet_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
framenum = pkt_q->framenum;
ppd = (struct tpacket2_hdr *) pkt_q->rd[framenum].iov_base;
for (i = 0; i < nb_pkts; i++) {
+ mbuf = *bufs++;
+
+ /* drop oversized packets */
+ if (rte_pktmbuf_data_len(mbuf) > pkt_q->frame_data_size) {
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
+
/* point at the next incoming frame */
if ((ppd->tp_status != TP_STATUS_AVAILABLE) &&
(poll(&pfd, 1, -1) < 0))
- continue;
+ break;
/* copy the tx frame data */
- mbuf = bufs[num_tx];
pbuf = (uint8_t *) ppd + TPACKET2_HDRLEN -
sizeof(struct sockaddr_ll);
memcpy(pbuf, rte_pktmbuf_mtod(mbuf, void*), rte_pktmbuf_data_len(mbuf));
@@ -231,13 +239,13 @@ eth_af_packet_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
/* kick-off transmits */
if (sendto(pkt_q->sockfd, NULL, 0, MSG_DONTWAIT, NULL, 0) == -1)
- return 0; /* error sending -- no packets transmitted */
+ num_tx = 0; /* error sending -- no packets transmitted */
pkt_q->framenum = framenum;
pkt_q->tx_pkts += num_tx;
- pkt_q->err_pkts += nb_pkts - num_tx;
+ pkt_q->err_pkts += i - num_tx;
pkt_q->tx_bytes += num_tx_bytes;
- return num_tx;
+ return i;
}
static int
@@ -634,6 +642,8 @@ rte_pmd_init_internals(const char *name,
tx_queue = &((*internals)->tx_queue[q]);
tx_queue->framecount = req->tp_frame_nr;
+ tx_queue->frame_data_size = req->tp_frame_size;
+ tx_queue->frame_data_size -= TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);
tx_queue->map = rx_queue->map + req->tp_block_size * req->tp_block_nr;
--
2.10.2
^ permalink raw reply related
* [PATCH v2 08/13] PMD/af_packet: guard against buffer overruns in RX path
From: Michał Mirosław @ 2016-12-13 1:28 UTC (permalink / raw)
To: dev, test-report
In-Reply-To: <20161213010918.F1B095684@dpdk.org>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/af_packet/rte_eth_af_packet.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index ff45068..5599e02 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -370,18 +370,19 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
{
struct pmd_internals *internals = dev->data->dev_private;
struct pkt_rx_queue *pkt_q = &internals->rx_queue[rx_queue_id];
- uint16_t buf_size;
+ unsigned int buf_size, data_size;
pkt_q->mb_pool = mb_pool;
/* Now get the space available for data in the mbuf */
- buf_size = (uint16_t)(rte_pktmbuf_data_room_size(pkt_q->mb_pool) -
- RTE_PKTMBUF_HEADROOM);
+ buf_size = rte_pktmbuf_data_room_size(pkt_q->mb_pool) - RTE_PKTMBUF_HEADROOM;
+ data_size = internals->req.tp_frame_size;
+ data_size -= TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);
- if (ETH_FRAME_LEN > buf_size) {
+ if (data_size > buf_size) {
RTE_LOG(ERR, PMD,
"%s: %d bytes will not fit in mbuf (%d bytes)\n",
- dev->data->name, ETH_FRAME_LEN, buf_size);
+ dev->data->name, data_size, buf_size);
return -ENOMEM;
}
--
2.10.2
^ permalink raw reply related
* [PATCH v2 06/13] null: fake PMD capabilities
From: Michał Mirosław @ 2016-12-13 1:28 UTC (permalink / raw)
To: dev
In-Reply-To: <20161213010913.34C8B5597@dpdk.org>
From: Paweł Małachowski <pawel.malachowski@atendesoftware.pl>
Thanks to that change we can use Null PMD for testing purposes.
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/null/rte_eth_null.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 836d982..09d53b0 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -284,6 +284,9 @@ eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
return 0;
}
+static void
+eth_dev_void_ok(struct rte_eth_dev *dev __rte_unused) { return; }
+
static void
eth_dev_info(struct rte_eth_dev *dev,
@@ -304,6 +307,11 @@ eth_dev_info(struct rte_eth_dev *dev,
dev_info->pci_dev = NULL;
dev_info->reta_size = internals->reta_size;
dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
+ /* We hereby declare we can RX offload VLAN-s out of thin air and update
+ * checksums and VLANs before sinking packets in /dev/null */
+ dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
+ dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+ DEV_TX_OFFLOAD_IPV4_CKSUM;
}
static void
@@ -477,7 +485,12 @@ static const struct eth_dev_ops ops = {
.reta_update = eth_rss_reta_update,
.reta_query = eth_rss_reta_query,
.rss_hash_update = eth_rss_hash_update,
- .rss_hash_conf_get = eth_rss_hash_conf_get
+ .rss_hash_conf_get = eth_rss_hash_conf_get,
+ /* Fake our capabilities */
+ .promiscuous_enable = eth_dev_void_ok,
+ .promiscuous_disable = eth_dev_void_ok,
+ .allmulticast_enable = eth_dev_void_ok,
+ .allmulticast_disable = eth_dev_void_ok
};
int
--
2.10.2
^ permalink raw reply related
* [PATCH v2 01/13] EAL: count nr_overcommit_hugepages as available
From: Michał Mirosław @ 2016-12-13 1:28 UTC (permalink / raw)
To: dev, test-report
In-Reply-To: <20161213010852.862C4376C@dpdk.org>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 43 ++++++++++++++++++-------
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c b/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
index 18858e2..b68f060 100644
--- a/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
+++ b/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
@@ -61,30 +61,38 @@
static const char sys_dir_path[] = "/sys/kernel/mm/hugepages";
+static int get_hp_sysfs_value(const char *subdir, const char *file, unsigned long *val)
+{
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof(path), "%s/%s/%s",
+ sys_dir_path, subdir, file);
+ return eal_parse_sysfs_value(path, val);
+}
+
/* this function is only called from eal_hugepage_info_init which itself
* is only called from a primary process */
static uint32_t
get_num_hugepages(const char *subdir)
{
- char path[PATH_MAX];
- long unsigned resv_pages, num_pages = 0;
+ unsigned long resv_pages, num_pages, over_pages, surplus_pages;
const char *nr_hp_file = "free_hugepages";
const char *nr_rsvd_file = "resv_hugepages";
+ const char *nr_over_file = "nr_overcommit_hugepages";
+ const char *nr_splus_file = "surplus_hugepages";
/* first, check how many reserved pages kernel reports */
- snprintf(path, sizeof(path), "%s/%s/%s",
- sys_dir_path, subdir, nr_rsvd_file);
- if (eal_parse_sysfs_value(path, &resv_pages) < 0)
+ if (get_hp_sysfs_value(subdir, nr_rsvd_file, &resv_pages) < 0)
return 0;
- snprintf(path, sizeof(path), "%s/%s/%s",
- sys_dir_path, subdir, nr_hp_file);
- if (eal_parse_sysfs_value(path, &num_pages) < 0)
+ if (get_hp_sysfs_value(subdir, nr_hp_file, &num_pages) < 0)
return 0;
- if (num_pages == 0)
- RTE_LOG(WARNING, EAL, "No free hugepages reported in %s\n",
- subdir);
+ if (get_hp_sysfs_value(subdir, nr_over_file, &over_pages) < 0)
+ over_pages = 0;
+
+ if (get_hp_sysfs_value(subdir, nr_splus_file, &surplus_pages) < 0)
+ surplus_pages = 0;
/* adjust num_pages */
if (num_pages >= resv_pages)
@@ -92,6 +100,19 @@ get_num_hugepages(const char *subdir)
else if (resv_pages)
num_pages = 0;
+ if (over_pages >= surplus_pages)
+ over_pages -= surplus_pages;
+ else
+ over_pages = 0;
+
+ if (num_pages == 0 && over_pages == 0)
+ RTE_LOG(WARNING, EAL, "No available hugepages reported in %s\n",
+ subdir);
+
+ num_pages += over_pages;
+ if (num_pages < over_pages) /* overflow */
+ num_pages = UINT32_MAX;
+
/* we want to return a uint32_t and more than this looks suspicious
* anyway ... */
if (num_pages > UINT32_MAX)
--
2.10.2
^ permalink raw reply related
* [PATCH 13/13] i40e: improve message grepability
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/i40e/i40e_ethdev.c | 198 +++++++++++++++--------------------------
1 file changed, 73 insertions(+), 125 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 39fbcfe..4d73aca 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -763,8 +763,7 @@ i40e_add_tx_flow_control_drop_filter(struct i40e_pf *pf)
pf->main_vsi_seid, 0,
TRUE, NULL, NULL);
if (ret)
- PMD_INIT_LOG(ERR, "Failed to add filter to drop flow control "
- " frames from VSIs.");
+ PMD_INIT_LOG(ERR, "Failed to add filter to drop flow control frames from VSIs.");
}
static int
@@ -963,8 +962,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
hw->back = I40E_PF_TO_ADAPTER(pf);
hw->hw_addr = (uint8_t *)(pci_dev->mem_resource[0].addr);
if (!hw->hw_addr) {
- PMD_INIT_LOG(ERR, "Hardware is not available, "
- "as address is NULL");
+ PMD_INIT_LOG(ERR, "Hardware is not available, as address is NULL");
return -ENODEV;
}
@@ -1100,8 +1098,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
/* Set the global registers with default ether type value */
ret = i40e_vlan_tpid_set(dev, ETH_VLAN_TYPE_OUTER, ETHER_TYPE_VLAN);
if (ret != I40E_SUCCESS) {
- PMD_INIT_LOG(ERR, "Failed to set the default outer "
- "VLAN ether type");
+ PMD_INIT_LOG(ERR, "Failed to set the default outer VLAN ether type");
goto err_setup_pf_switch;
}
@@ -1137,8 +1134,7 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
/* Should be after VSI initialized */
dev->data->mac_addrs = rte_zmalloc("i40e", len, 0);
if (!dev->data->mac_addrs) {
- PMD_INIT_LOG(ERR, "Failed to allocated memory "
- "for storing mac address");
+ PMD_INIT_LOG(ERR, "Failed to allocated memory for storing mac address");
goto err_mac_alloc;
}
ether_addr_copy((struct ether_addr *)hw->mac.perm_addr,
@@ -1703,8 +1699,9 @@ i40e_dev_start(struct rte_eth_dev *dev)
dev->data->nb_rx_queues * sizeof(int),
0);
if (!intr_handle->intr_vec) {
- PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues"
- " intr_vec\n", dev->data->nb_rx_queues);
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate %d rx_queues intr_vec\n",
+ dev->data->nb_rx_queues);
return -ENOMEM;
}
}
@@ -1777,8 +1774,8 @@ i40e_dev_start(struct rte_eth_dev *dev)
i40e_pf_enable_irq0(hw);
if (dev->data->dev_conf.intr_conf.lsc != 0)
- PMD_INIT_LOG(INFO, "lsc won't enable because of"
- " no intr multiplex\n");
+ PMD_INIT_LOG(INFO,
+ "lsc won't enable because of no intr multiplex\n");
} else if (dev->data->dev_conf.intr_conf.lsc != 0) {
ret = i40e_aq_set_phy_int_mask(hw,
~(I40E_AQ_EVENT_LINK_UPDOWN |
@@ -2718,13 +2715,11 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
ret = i40e_aq_debug_read_register(hw, I40E_GL_SWT_L2TAGCTRL(reg_id),
®_r, NULL);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Fail to debug read from "
- "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
+ PMD_DRV_LOG(ERR, "Fail to debug read from I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
ret = -EIO;
return ret;
}
- PMD_DRV_LOG(DEBUG, "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: "
- "0x%08"PRIx64"", reg_id, reg_r);
+ PMD_DRV_LOG(DEBUG, "Debug read from I40E_GL_SWT_L2TAGCTRL[%d]: 0x%08"PRIx64"", reg_id, reg_r);
reg_w = reg_r & (~(I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_MASK));
reg_w |= ((uint64_t)tpid << I40E_GL_SWT_L2TAGCTRL_ETHERTYPE_SHIFT);
@@ -2738,12 +2733,10 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
reg_w, NULL);
if (ret != I40E_SUCCESS) {
ret = -EIO;
- PMD_DRV_LOG(ERR, "Fail to debug write to "
- "I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
+ PMD_DRV_LOG(ERR, "Fail to debug write to I40E_GL_SWT_L2TAGCTRL[%d]", reg_id);
return ret;
}
- PMD_DRV_LOG(DEBUG, "Debug write 0x%08"PRIx64" to "
- "I40E_GL_SWT_L2TAGCTRL[%d]", reg_w, reg_id);
+ PMD_DRV_LOG(DEBUG, "Debug write 0x%08"PRIx64" to I40E_GL_SWT_L2TAGCTRL[%d]", reg_w, reg_id);
return ret;
}
@@ -2887,8 +2880,7 @@ i40e_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
max_high_water = I40E_RXPBSIZE >> I40E_KILOSHIFT;
if ((fc_conf->high_water > max_high_water) ||
(fc_conf->high_water < fc_conf->low_water)) {
- PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB, "
- "High_water must <= %d.", max_high_water);
+ PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB, High_water must be <= %d.", max_high_water);
return -EINVAL;
}
@@ -3060,8 +3052,7 @@ i40e_macaddr_remove(struct rte_eth_dev *dev, uint32_t index)
/* No VMDQ pool enabled or configured */
if (!(pf->flags & I40E_FLAG_VMDQ) ||
(i > pf->nb_cfg_vmdq_vsi)) {
- PMD_DRV_LOG(ERR, "No VMDQ pool enabled"
- "/configured");
+ PMD_DRV_LOG(ERR, "No VMDQ pool enabled/configured");
return;
}
vsi = pf->vmdq[i - 1].vsi;
@@ -3262,9 +3253,8 @@ i40e_dev_rss_reta_update(struct rte_eth_dev *dev,
if (reta_size != lut_size ||
reta_size > ETH_RSS_RETA_SIZE_512) {
- PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
- "(%d) doesn't match the number hardware can supported "
- "(%d)\n", reta_size, lut_size);
+ PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d) doesn't match the number hardware can supported (%d)\n",
+ reta_size, lut_size);
return -EINVAL;
}
@@ -3303,9 +3293,8 @@ i40e_dev_rss_reta_query(struct rte_eth_dev *dev,
if (reta_size != lut_size ||
reta_size > ETH_RSS_RETA_SIZE_512) {
- PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
- "(%d) doesn't match the number hardware can supported "
- "(%d)\n", reta_size, lut_size);
+ PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d) doesn't match the number hardware can supported (%d)\n",
+ reta_size, lut_size);
return -EINVAL;
}
@@ -3538,9 +3527,8 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
pf->flags |= I40E_FLAG_SRIOV;
pf->vf_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF;
pf->vf_num = dev->pci_dev->max_vfs;
- PMD_DRV_LOG(DEBUG, "%u VF VSIs, %u queues per VF VSI, "
- "in total %u queues", pf->vf_num, pf->vf_nb_qps,
- pf->vf_nb_qps * pf->vf_num);
+ PMD_DRV_LOG(DEBUG, "%u VF VSIs, %u queues per VF VSI, in total %u queues",
+ pf->vf_num, pf->vf_nb_qps, pf->vf_nb_qps * pf->vf_num);
} else {
pf->vf_nb_qps = 0;
pf->vf_num = 0;
@@ -3568,14 +3556,12 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
if (pf->max_nb_vmdq_vsi) {
pf->flags |= I40E_FLAG_VMDQ;
pf->vmdq_nb_qps = pf->vmdq_nb_qp_max;
- PMD_DRV_LOG(DEBUG, "%u VMDQ VSIs, %u queues "
- "per VMDQ VSI, in total %u queues",
+ PMD_DRV_LOG(DEBUG, "%u VMDQ VSIs, %u queues per VMDQ VSI, in total %u queues",
pf->max_nb_vmdq_vsi,
pf->vmdq_nb_qps, pf->vmdq_nb_qps *
pf->max_nb_vmdq_vsi);
} else {
- PMD_DRV_LOG(INFO, "No enough queues left for "
- "VMDq");
+ PMD_DRV_LOG(INFO, "No enough queues left for VMDq");
}
} else {
PMD_DRV_LOG(INFO, "No queue or VSI left for VMDq");
@@ -3588,15 +3574,13 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev)
pf->flags |= I40E_FLAG_DCB;
if (qp_count > hw->func_caps.num_tx_qp) {
- PMD_DRV_LOG(ERR, "Failed to allocate %u queues, which exceeds "
- "the hardware maximum %u", qp_count,
- hw->func_caps.num_tx_qp);
+ PMD_DRV_LOG(ERR, "Failed to allocate %u queues, which exceeds the hardware maximum %u",
+ qp_count, hw->func_caps.num_tx_qp);
return -EINVAL;
}
if (vsi_count > hw->func_caps.num_vsis) {
- PMD_DRV_LOG(ERR, "Failed to allocate %u VSIs, which exceeds "
- "the hardware maximum %u", vsi_count,
- hw->func_caps.num_vsis);
+ PMD_DRV_LOG(ERR, "Failed to allocate %u VSIs, which exceeds the hardware maximum %u",
+ vsi_count, hw->func_caps.num_vsis);
return -EINVAL;
}
@@ -3842,8 +3826,7 @@ i40e_res_pool_alloc(struct i40e_res_pool_info *pool,
*/
entry = rte_zmalloc("res_pool", sizeof(*entry), 0);
if (entry == NULL) {
- PMD_DRV_LOG(ERR, "Failed to allocate memory for "
- "resource pool");
+ PMD_DRV_LOG(ERR, "Failed to allocate memory for resource pool");
return -ENOMEM;
}
entry->base = valid_entry->base;
@@ -3883,9 +3866,8 @@ validate_tcmap_parameter(struct i40e_vsi *vsi, uint8_t enabled_tcmap)
}
if (!bitmap_is_subset(hw->func_caps.enabled_tcmap, enabled_tcmap)) {
- PMD_DRV_LOG(ERR, "Enabled TC map 0x%x not applicable to "
- "HW support 0x%x", hw->func_caps.enabled_tcmap,
- enabled_tcmap);
+ PMD_DRV_LOG(ERR, "Enabled TC map 0x%x not applicable to HW support 0x%x",
+ hw->func_caps.enabled_tcmap, enabled_tcmap);
return I40E_NOT_SUPPORTED;
}
return I40E_SUCCESS;
@@ -4227,8 +4209,7 @@ i40e_update_default_filter_setting(struct i40e_vsi *vsi)
struct i40e_mac_filter *f;
struct ether_addr *mac;
- PMD_DRV_LOG(WARNING, "Cannot remove the default "
- "macvlan filter");
+ PMD_DRV_LOG(WARNING, "Cannot remove the default macvlan filter");
/* It needs to add the permanent mac into mac list */
f = rte_zmalloc("macv_filter", sizeof(*f), 0);
if (f == NULL) {
@@ -4278,8 +4259,8 @@ i40e_vsi_get_bw_config(struct i40e_vsi *vsi)
ret = i40e_aq_query_vsi_ets_sla_config(hw, vsi->seid,
&ets_sla_config, NULL);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "VSI failed to get TC bandwdith "
- "configuration %u", hw->aq.asq_last_status);
+ PMD_DRV_LOG(ERR, "VSI failed to get TC bandwdith configuration %u",
+ hw->aq.asq_last_status);
return ret;
}
@@ -4367,14 +4348,12 @@ i40e_vsi_setup(struct i40e_pf *pf,
if (type != I40E_VSI_MAIN && type != I40E_VSI_SRIOV &&
uplink_vsi == NULL) {
- PMD_DRV_LOG(ERR, "VSI setup failed, "
- "VSI link shouldn't be NULL");
+ PMD_DRV_LOG(ERR, "VSI setup failed, VSI link shouldn't be NULL");
return NULL;
}
if (type == I40E_VSI_MAIN && uplink_vsi != NULL) {
- PMD_DRV_LOG(ERR, "VSI setup failed, MAIN VSI "
- "uplink VSI should be NULL");
+ PMD_DRV_LOG(ERR, "VSI setup failed, MAIN VSI uplink VSI should be NULL");
return NULL;
}
@@ -4525,8 +4504,7 @@ i40e_vsi_setup(struct i40e_pf *pf,
ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
I40E_DEFAULT_TCMAP);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to configure "
- "TC queue mapping");
+ PMD_DRV_LOG(ERR, "Failed to configure TC queue mapping");
goto fail_msix_alloc;
}
ctxt.seid = vsi->seid;
@@ -4596,8 +4574,7 @@ i40e_vsi_setup(struct i40e_pf *pf,
ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
I40E_DEFAULT_TCMAP);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to configure "
- "TC queue mapping");
+ PMD_DRV_LOG(ERR, "Failed to configure TC queue mapping");
goto fail_msix_alloc;
}
ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;
@@ -4639,8 +4616,7 @@ i40e_vsi_setup(struct i40e_pf *pf,
ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
I40E_DEFAULT_TCMAP);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to configure "
- "TC queue mapping");
+ PMD_DRV_LOG(ERR, "Failed to configure TC queue mapping");
goto fail_msix_alloc;
}
ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;
@@ -4657,8 +4633,7 @@ i40e_vsi_setup(struct i40e_pf *pf,
ret = i40e_vsi_config_tc_queue_mapping(vsi, &ctxt.info,
I40E_DEFAULT_TCMAP);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to configure "
- "TC queue mapping.");
+ PMD_DRV_LOG(ERR, "Failed to configure TC queue mapping.");
goto fail_msix_alloc;
}
ctxt.info.up_enable_bits = I40E_DEFAULT_TCMAP;
@@ -4921,8 +4896,7 @@ i40e_pf_setup(struct i40e_pf *pf)
/* make queue allocated first, let FDIR use queue pair 0*/
ret = i40e_res_pool_alloc(&pf->qp_pool, I40E_DEFAULT_QP_NUM_FDIR);
if (ret != I40E_FDIR_QUEUE_ID) {
- PMD_DRV_LOG(ERR, "queue allocation fails for FDIR :"
- " ret =%d", ret);
+ PMD_DRV_LOG(ERR, "queue allocation fails for FDIR: ret =%d", ret);
pf->flags &= ~I40E_FLAG_FDIR;
}
}
@@ -4945,8 +4919,8 @@ i40e_pf_setup(struct i40e_pf *pf)
hw->func_caps.rss_table_size);
return I40E_ERR_PARAM;
}
- PMD_DRV_LOG(INFO, "Hardware capability of hash lookup table "
- "size: %u\n", hw->func_caps.rss_table_size);
+ PMD_DRV_LOG(INFO, "Hardware capability of hash lookup table size: %u\n",
+ hw->func_caps.rss_table_size);
pf->hash_lut_size = hw->func_caps.rss_table_size;
/* Enable ethtype and macvlan filters */
@@ -5196,8 +5170,7 @@ i40e_dev_rx_init(struct i40e_pf *pf)
ret = i40e_rx_queue_init(rxq);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to do RX queue "
- "initialization");
+ PMD_DRV_LOG(ERR, "Failed to do RX queue initialization");
break;
}
}
@@ -5481,8 +5454,8 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
ret = i40e_clean_arq_element(hw, &info, &pending);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ, "
- "aq_err: %u", hw->aq.asq_last_status);
+ PMD_DRV_LOG(INFO, "Failed to read msg from AdminQ, aq_err: %u",
+ hw->aq.asq_last_status);
break;
}
opcode = rte_le_to_cpu_16(info.desc.opcode);
@@ -5799,8 +5772,7 @@ i40e_find_all_vlan_for_mac(struct i40e_vsi *vsi,
for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
if (vsi->vfta[j] & (1 << k)) {
if (i > num - 1) {
- PMD_DRV_LOG(ERR, "vlan number "
- "not match");
+ PMD_DRV_LOG(ERR, "vlan number not match");
return I40E_ERR_PARAM;
}
(void)rte_memcpy(&mv_f[i].macaddr,
@@ -6281,8 +6253,7 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len)
ret = i40e_aq_set_rss_key(hw, vsi->vsi_id, key_dw);
if (ret)
- PMD_INIT_LOG(ERR, "Failed to configure RSS key "
- "via AQ");
+ PMD_INIT_LOG(ERR, "Failed to configure RSS key via AQ");
} else {
uint32_t *hash_key = (uint32_t *)key;
uint16_t i;
@@ -6546,8 +6517,7 @@ i40e_add_vxlan_port(struct i40e_pf *pf, uint16_t port)
/* Now check if there is space to add the new port */
idx = i40e_get_vxlan_port_idx(pf, 0);
if (idx < 0) {
- PMD_DRV_LOG(ERR, "Maximum number of UDP ports reached,"
- "not adding port %d", port);
+ PMD_DRV_LOG(ERR, "Maximum number of UDP ports reached, not adding port %d", port);
return -ENOSPC;
}
@@ -6918,15 +6888,13 @@ i40e_set_symmetric_hash_enable_per_port(struct i40e_hw *hw, uint8_t enable)
if (enable > 0) {
if (reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK) {
- PMD_DRV_LOG(INFO, "Symmetric hash has already "
- "been enabled");
+ PMD_DRV_LOG(INFO, "Symmetric hash has already been enabled");
return;
}
reg |= I40E_PRTQF_CTL_0_HSYM_ENA_MASK;
} else {
if (!(reg & I40E_PRTQF_CTL_0_HSYM_ENA_MASK)) {
- PMD_DRV_LOG(INFO, "Symmetric hash has already "
- "been disabled");
+ PMD_DRV_LOG(INFO, "Symmetric hash has already been disabled");
return;
}
reg &= ~I40E_PRTQF_CTL_0_HSYM_ENA_MASK;
@@ -7050,16 +7018,14 @@ i40e_set_hash_filter_global_config(struct i40e_hw *hw,
if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_TOEPLITZ) {
/* Toeplitz */
if (reg & I40E_GLQF_CTL_HTOEP_MASK) {
- PMD_DRV_LOG(DEBUG, "Hash function already set to "
- "Toeplitz");
+ PMD_DRV_LOG(DEBUG, "Hash function already set to Toeplitz");
goto out;
}
reg |= I40E_GLQF_CTL_HTOEP_MASK;
} else if (g_cfg->hash_func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {
/* Simple XOR */
if (!(reg & I40E_GLQF_CTL_HTOEP_MASK)) {
- PMD_DRV_LOG(DEBUG, "Hash function already set to "
- "Simple XOR");
+ PMD_DRV_LOG(DEBUG, "Hash function already set to Simple XOR");
goto out;
}
reg &= ~I40E_GLQF_CTL_HTOEP_MASK;
@@ -8007,13 +7973,12 @@ i40e_ethertype_filter_set(struct i40e_pf *pf,
}
if (filter->ether_type == ETHER_TYPE_IPv4 ||
filter->ether_type == ETHER_TYPE_IPv6) {
- PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in"
- " control packet filter.", filter->ether_type);
+ PMD_DRV_LOG(ERR, "unsupported ether_type(0x%04x) in control packet filter.",
+ filter->ether_type);
return -EINVAL;
}
if (filter->ether_type == ETHER_TYPE_VLAN)
- PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is"
- " not supported.");
+ PMD_DRV_LOG(WARNING, "filter vlan ether_type in first tag is not supported.");
if (!(filter->flags & RTE_ETHTYPE_FLAGS_MAC))
flags |= I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC;
@@ -8340,9 +8305,8 @@ i40e_configure_registers(struct i40e_hw *hw)
ret = i40e_aq_debug_write_register(hw, reg_table[i].addr,
reg_table[i].val, NULL);
if (ret < 0) {
- PMD_DRV_LOG(ERR, "Failed to write 0x%"PRIx64" to the "
- "address of 0x%"PRIx32, reg_table[i].val,
- reg_table[i].addr);
+ PMD_DRV_LOG(ERR, "Failed to write 0x%"PRIx64" to the address of 0x%"PRIx32,
+ reg_table[i].val, reg_table[i].addr);
break;
}
PMD_DRV_LOG(DEBUG, "Write 0x%"PRIx64" to the address of "
@@ -8387,8 +8351,7 @@ i40e_config_qinq(struct i40e_hw *hw, struct i40e_vsi *vsi)
I40E_VSI_L2TAGSTXVALID(
vsi->vsi_id), reg, NULL);
if (ret < 0) {
- PMD_DRV_LOG(ERR, "Failed to update "
- "VSI_L2TAGSTXVALID[%d]", vsi->vsi_id);
+ PMD_DRV_LOG(ERR, "Failed to update VSI_L2TAGSTXVALID[%d]", vsi->vsi_id);
return I40E_ERR_CONFIG;
}
}
@@ -8439,8 +8402,7 @@ i40e_aq_add_mirror_rule(struct i40e_hw *hw,
rte_memcpy(&desc.params.raw, &cmd, sizeof(cmd));
status = i40e_asq_send_command(hw, &desc, entries, buff_len, NULL);
- PMD_DRV_LOG(INFO, "i40e_aq_add_mirror_rule, aq_status %d,"
- "rule_id = %u"
+ PMD_DRV_LOG(INFO, "i40e_aq_add_mirror_rule, aq_status %d, rule_id = %u"
" mirror_rules_used = %u, mirror_rules_free = %u,",
hw->aq.asq_last_status, resp->rule_id,
resp->mirror_rules_used, resp->mirror_rules_free);
@@ -8521,8 +8483,7 @@ i40e_mirror_rule_set(struct rte_eth_dev *dev,
PMD_DRV_LOG(DEBUG, "i40e_mirror_rule_set: sw_id = %d.", sw_id);
if (pf->main_vsi->veb == NULL || pf->vfs == NULL) {
- PMD_DRV_LOG(ERR, "mirror rule can not be configured"
- " without veb or vfs.");
+ PMD_DRV_LOG(ERR, "mirror rule can not be configured without veb or vfs.");
return -ENOSYS;
}
if (pf->nb_mirror_rule > I40E_MAX_MIRROR_RULES) {
@@ -8554,8 +8515,7 @@ i40e_mirror_rule_set(struct rte_eth_dev *dev,
mirr_rule->entries,
mirr_rule->num_entries, mirr_rule->id);
if (ret < 0) {
- PMD_DRV_LOG(ERR, "failed to remove mirror rule:"
- " ret = %d, aq_err = %d.",
+ PMD_DRV_LOG(ERR, "failed to remove mirror rule: ret = %d, aq_err = %d.",
ret, hw->aq.asq_last_status);
return -ENOSYS;
}
@@ -8645,8 +8605,7 @@ i40e_mirror_rule_set(struct rte_eth_dev *dev,
mirr_rule->rule_type, mirr_rule->entries,
j, &rule_id);
if (ret < 0) {
- PMD_DRV_LOG(ERR, "failed to add mirror rule:"
- " ret = %d, aq_err = %d.",
+ PMD_DRV_LOG(ERR, "failed to add mirror rule: ret = %d, aq_err = %d.",
ret, hw->aq.asq_last_status);
rte_free(mirr_rule);
return -ENOSYS;
@@ -8699,8 +8658,7 @@ i40e_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t sw_id)
mirr_rule->entries,
mirr_rule->num_entries, mirr_rule->id);
if (ret < 0) {
- PMD_DRV_LOG(ERR, "failed to remove mirror rule:"
- " status = %d, aq_err = %d.",
+ PMD_DRV_LOG(ERR, "failed to remove mirror rule: status = %d, aq_err = %d.",
ret, hw->aq.asq_last_status);
return -ENOSYS;
}
@@ -9133,8 +9091,7 @@ i40e_config_switch_comp_tc(struct i40e_veb *veb, uint8_t tc_map)
ret = i40e_aq_config_switch_comp_bw_config(hw, veb->seid,
&veb_bw, NULL);
if (ret) {
- PMD_INIT_LOG(ERR, "AQ command Config switch_comp BW allocation"
- " per TC failed = %d",
+ PMD_INIT_LOG(ERR, "AQ command Config switch_comp BW allocation per TC failed = %d",
hw->aq.asq_last_status);
return ret;
}
@@ -9143,16 +9100,14 @@ i40e_config_switch_comp_tc(struct i40e_veb *veb, uint8_t tc_map)
ret = i40e_aq_query_switch_comp_ets_config(hw, veb->seid,
&ets_query, NULL);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to get switch_comp ETS"
- " configuration %u", hw->aq.asq_last_status);
+ PMD_DRV_LOG(ERR, "Failed to get switch_comp ETS configuration %u", hw->aq.asq_last_status);
return ret;
}
memset(&bw_query, 0, sizeof(bw_query));
ret = i40e_aq_query_switch_comp_bw_config(hw, veb->seid,
&bw_query, NULL);
if (ret != I40E_SUCCESS) {
- PMD_DRV_LOG(ERR, "Failed to get switch_comp bandwidth"
- " configuration %u", hw->aq.asq_last_status);
+ PMD_DRV_LOG(ERR, "Failed to get switch_comp bandwidth configuration %u", hw->aq.asq_last_status);
return ret;
}
@@ -9217,8 +9172,7 @@ i40e_vsi_config_tc(struct i40e_vsi *vsi, uint8_t tc_map)
}
ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &bw_data, NULL);
if (ret) {
- PMD_INIT_LOG(ERR, "AQ command Config VSI BW allocation"
- " per TC failed = %d",
+ PMD_INIT_LOG(ERR, "AQ command Config VSI BW allocation per TC failed = %d",
hw->aq.asq_last_status);
goto out;
}
@@ -9239,8 +9193,7 @@ i40e_vsi_config_tc(struct i40e_vsi *vsi, uint8_t tc_map)
/* Update the VSI after updating the VSI queue-mapping information */
ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
if (ret) {
- PMD_INIT_LOG(ERR, "Failed to configure "
- "TC queue mapping = %d",
+ PMD_INIT_LOG(ERR, "Failed to configure TC queue mapping = %d",
hw->aq.asq_last_status);
goto out;
}
@@ -9293,8 +9246,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
/* Use the FW API if FW > v4.4*/
if (!(((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver >= 4)) ||
(hw->aq.fw_maj_ver >= 5))) {
- PMD_INIT_LOG(ERR, "FW < v4.4, can not use FW LLDP API"
- " to configure DCB");
+ PMD_INIT_LOG(ERR, "FW < v4.4, can not use FW LLDP API to configure DCB");
return I40E_ERR_FIRMWARE_API_VERSION;
}
@@ -9421,14 +9373,12 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
I40E_APP_PROTOID_FCOE;
ret = i40e_set_dcb_config(hw);
if (ret) {
- PMD_INIT_LOG(ERR, "default dcb config fails."
- " err = %d, aq_err = %d.", ret,
+ PMD_INIT_LOG(ERR, "default dcb config fails. err = %d, aq_err = %d.", ret,
hw->aq.asq_last_status);
return -ENOSYS;
}
} else {
- PMD_INIT_LOG(ERR, "DCB initialization in FW fails,"
- " err = %d, aq_err = %d.", ret,
+ PMD_INIT_LOG(ERR, "DCB initialization in FW fails, err = %d, aq_err = %d.", ret,
hw->aq.asq_last_status);
return -ENOTSUP;
}
@@ -9440,13 +9390,11 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
ret = i40e_init_dcb(hw);
if (!ret) {
if (hw->dcbx_status == I40E_DCBX_STATUS_DISABLED) {
- PMD_INIT_LOG(ERR, "HW doesn't support"
- " DCBX offload.");
+ PMD_INIT_LOG(ERR, "HW doesn't support DCBX offload.");
return -ENOTSUP;
}
} else {
- PMD_INIT_LOG(ERR, "DCBX configuration failed, err = %d,"
- " aq_err = %d.", ret,
+ PMD_INIT_LOG(ERR, "DCBX configuration failed, err = %d, aq_err = %d.", ret,
hw->aq.asq_last_status);
return -ENOTSUP;
}
--
2.10.2
^ permalink raw reply related
* [PATCH 12/13] i40e: return -errno when intr setup fails
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/i40e/i40e_ethdev.c | 5 +++--
lib/librte_eal/linuxapp/eal/eal_interrupts.c | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 67778ba..39fbcfe 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1692,8 +1692,9 @@ i40e_dev_start(struct rte_eth_dev *dev)
!RTE_ETH_DEV_SRIOV(dev).active) &&
dev->data->dev_conf.intr_conf.rxq != 0) {
intr_vector = dev->data->nb_rx_queues;
- if (rte_intr_efd_enable(intr_handle, intr_vector))
- return -1;
+ ret = rte_intr_efd_enable(intr_handle, intr_vector);
+ if (ret)
+ return ret;
}
if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
diff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
index 47a3b20..f7a8ce3 100644
--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c
+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c
@@ -1157,7 +1157,7 @@ rte_intr_efd_enable(struct rte_intr_handle *intr_handle, uint32_t nb_efd)
RTE_LOG(ERR, EAL,
"can't setup eventfd, error %i (%s)\n",
errno, strerror(errno));
- return -1;
+ return -errno;
}
intr_handle->efds[i] = fd;
}
--
2.10.2
^ permalink raw reply related
* [PATCH 11/13] KNI: guard against unterminated dev_info.name leading to BUG in alloc_netdev()
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_eal/linuxapp/kni/kni_misc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/librte_eal/linuxapp/kni/kni_misc.c b/lib/librte_eal/linuxapp/kni/kni_misc.c
index f0247aa..14a2e3b 100644
--- a/lib/librte_eal/linuxapp/kni/kni_misc.c
+++ b/lib/librte_eal/linuxapp/kni/kni_misc.c
@@ -344,6 +344,12 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
return -EIO;
}
+ /* Check if name is zero-ended */
+ if (strnlen(dev_info.name, sizeof(dev_info.name)) == sizeof(dev_info.name)) {
+ pr_err("kni.name not zero-terminated");
+ return -EINVAL;
+ }
+
/**
* Check if the cpu core id is valid for binding.
*/
--
2.10.2
^ permalink raw reply related
* [PATCH 10/13] KNI: provided netif name's source is user-space
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_eal/linuxapp/kni/kni_misc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/librte_eal/linuxapp/kni/kni_misc.c b/lib/librte_eal/linuxapp/kni/kni_misc.c
index 497db9b..f0247aa 100644
--- a/lib/librte_eal/linuxapp/kni/kni_misc.c
+++ b/lib/librte_eal/linuxapp/kni/kni_misc.c
@@ -363,8 +363,8 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
up_read(&knet->kni_list_lock);
net_dev = alloc_netdev(sizeof(struct kni_dev), dev_info.name,
-#ifdef NET_NAME_UNKNOWN
- NET_NAME_UNKNOWN,
+#ifdef NET_NAME_USER
+ NET_NAME_USER,
#endif
kni_net_init);
if (net_dev == NULL) {
--
2.10.2
^ permalink raw reply related
* [PATCH 09/13] PMD/af_packet: guard against buffer overruns in TX path
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/af_packet/rte_eth_af_packet.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index b1005c6..2c81d25 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -83,6 +83,7 @@ struct pkt_rx_queue {
struct pkt_tx_queue {
int sockfd;
+ unsigned frame_data_size;
struct iovec *rd;
uint8_t *map;
@@ -206,13 +207,20 @@ eth_af_packet_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
framenum = pkt_q->framenum;
ppd = (struct tpacket2_hdr *) pkt_q->rd[framenum].iov_base;
for (i = 0; i < nb_pkts; i++) {
+ mbuf = *bufs++;
+
+ /* drop oversized packets */
+ if (rte_pktmbuf_data_len(mbuf) > pkt_q->frame_data_size) {
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
+
/* point at the next incoming frame */
if ((ppd->tp_status != TP_STATUS_AVAILABLE) &&
(poll(&pfd, 1, -1) < 0))
- continue;
+ break;
/* copy the tx frame data */
- mbuf = bufs[num_tx];
pbuf = (uint8_t *) ppd + TPACKET2_HDRLEN -
sizeof(struct sockaddr_ll);
memcpy(pbuf, rte_pktmbuf_mtod(mbuf, void*), rte_pktmbuf_data_len(mbuf));
@@ -231,13 +239,13 @@ eth_af_packet_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
/* kick-off transmits */
if (sendto(pkt_q->sockfd, NULL, 0, MSG_DONTWAIT, NULL, 0) == -1)
- return 0; /* error sending -- no packets transmitted */
+ num_tx = 0; /* error sending -- no packets transmitted */
pkt_q->framenum = framenum;
pkt_q->tx_pkts += num_tx;
- pkt_q->err_pkts += nb_pkts - num_tx;
+ pkt_q->err_pkts += i - num_tx;
pkt_q->tx_bytes += num_tx_bytes;
- return num_tx;
+ return i;
}
static int
@@ -633,6 +641,7 @@ rte_pmd_init_internals(const char *name,
tx_queue = &((*internals)->tx_queue[q]);
tx_queue->framecount = req->tp_frame_nr;
+ tx_queue->frame_data_size = req->tp_frame_size - TPACKET2_HDRLEN + sizeof(struct sockaddr_ll);
tx_queue->map = rx_queue->map + req->tp_block_size * req->tp_block_nr;
--
2.10.2
^ permalink raw reply related
* [PATCH 08/13] PMD/af_packet: guard against buffer overruns in RX path
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/af_packet/rte_eth_af_packet.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/af_packet/rte_eth_af_packet.c b/drivers/net/af_packet/rte_eth_af_packet.c
index ff45068..b1005c6 100644
--- a/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/drivers/net/af_packet/rte_eth_af_packet.c
@@ -370,18 +370,18 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
{
struct pmd_internals *internals = dev->data->dev_private;
struct pkt_rx_queue *pkt_q = &internals->rx_queue[rx_queue_id];
- uint16_t buf_size;
+ unsigned buf_size, data_size;
pkt_q->mb_pool = mb_pool;
/* Now get the space available for data in the mbuf */
- buf_size = (uint16_t)(rte_pktmbuf_data_room_size(pkt_q->mb_pool) -
- RTE_PKTMBUF_HEADROOM);
+ buf_size = rte_pktmbuf_data_room_size(pkt_q->mb_pool) - RTE_PKTMBUF_HEADROOM;
+ data_size = internals->req.tp_frame_size - TPACKET2_HDRLEN + sizeof(struct sockaddr_ll);
- if (ETH_FRAME_LEN > buf_size) {
+ if (data_size > buf_size) {
RTE_LOG(ERR, PMD,
"%s: %d bytes will not fit in mbuf (%d bytes)\n",
- dev->data->name, ETH_FRAME_LEN, buf_size);
+ dev->data->name, data_size, buf_size);
return -ENOMEM;
}
--
2.10.2
^ permalink raw reply related
* [PATCH 07/13] pcap: fix timestamps in output pcap file
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
From: Piotr Bartosiewicz <piotr.bartosiewicz@atendesoftware.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/pcap/rte_eth_pcap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/pcap/rte_eth_pcap.c b/drivers/net/pcap/rte_eth_pcap.c
index 0162f44..57b0b31 100644
--- a/drivers/net/pcap/rte_eth_pcap.c
+++ b/drivers/net/pcap/rte_eth_pcap.c
@@ -247,7 +247,7 @@ calculate_timestamp(struct timeval *ts) {
cycles = rte_get_timer_cycles() - start_cycles;
cur_time.tv_sec = cycles / hz;
- cur_time.tv_usec = (cycles % hz) * 10e6 / hz;
+ cur_time.tv_usec = (cycles % hz) * 1e6 / hz;
timeradd(&start_time, &cur_time, ts);
}
--
2.10.2
^ permalink raw reply related
* [PATCH 06/13] null: fake PMD capabilities
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
From: Paweł Małachowski <pawel.malachowski@atendesoftware.pl>
Thanks to that change we can use Null PMD for testing purposes.
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
drivers/net/null/rte_eth_null.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/net/null/rte_eth_null.c b/drivers/net/null/rte_eth_null.c
index 836d982..f32ba2a 100644
--- a/drivers/net/null/rte_eth_null.c
+++ b/drivers/net/null/rte_eth_null.c
@@ -284,6 +284,9 @@ eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
return 0;
}
+static void
+eth_dev_void_ok(struct rte_eth_dev *dev __rte_unused) { return; }
+
static void
eth_dev_info(struct rte_eth_dev *dev,
@@ -304,6 +307,9 @@ eth_dev_info(struct rte_eth_dev *dev,
dev_info->pci_dev = NULL;
dev_info->reta_size = internals->reta_size;
dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
+ /* We hereby declare we can RX-offload VLAN-s out of thin air and update checksums and VLANs before sinking packets in /dev/null */
+ dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP;
+ dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT | DEV_TX_OFFLOAD_IPV4_CKSUM;
}
static void
@@ -477,7 +483,12 @@ static const struct eth_dev_ops ops = {
.reta_update = eth_rss_reta_update,
.reta_query = eth_rss_reta_query,
.rss_hash_update = eth_rss_hash_update,
- .rss_hash_conf_get = eth_rss_hash_conf_get
+ .rss_hash_conf_get = eth_rss_hash_conf_get,
+ /* Fake our capabilities */
+ .promiscuous_enable = eth_dev_void_ok,
+ .promiscuous_disable = eth_dev_void_ok,
+ .allmulticast_enable = eth_dev_void_ok,
+ .allmulticast_disable = eth_dev_void_ok
};
int
--
2.10.2
^ permalink raw reply related
* [PATCH 05/13] acl: fix acl_flow_data comments
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_acl/acl_run.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/librte_acl/acl_run.h b/lib/librte_acl/acl_run.h
index 024f393..a862ff6 100644
--- a/lib/librte_acl/acl_run.h
+++ b/lib/librte_acl/acl_run.h
@@ -69,10 +69,10 @@ struct acl_flow_data {
uint32_t trie;
/* current trie index (0 to N-1) */
uint32_t cmplt_size;
+ /* maximum number of packets to process */
uint32_t total_packets;
- uint32_t categories;
/* number of result categories per packet. */
- /* maximum number of packets to process */
+ uint32_t categories;
const uint64_t *trans;
const uint8_t **data;
uint32_t *results;
--
2.10.2
^ permalink raw reply related
* [PATCH 04/13] acl: allow zero verdict
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_acl/rte_acl.c | 3 +--
lib/librte_acl/rte_acl.h | 2 --
lib/librte_table/rte_table_acl.c | 2 +-
3 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 8b7e92c..d1f40be 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -313,8 +313,7 @@ acl_check_rule(const struct rte_acl_rule_data *rd)
if ((RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES, typeof(rd->category_mask)) &
rd->category_mask) == 0 ||
rd->priority > RTE_ACL_MAX_PRIORITY ||
- rd->priority < RTE_ACL_MIN_PRIORITY ||
- rd->userdata == RTE_ACL_INVALID_USERDATA)
+ rd->priority < RTE_ACL_MIN_PRIORITY)
return -EINVAL;
return 0;
}
diff --git a/lib/librte_acl/rte_acl.h b/lib/librte_acl/rte_acl.h
index caa91f7..b53179a 100644
--- a/lib/librte_acl/rte_acl.h
+++ b/lib/librte_acl/rte_acl.h
@@ -120,8 +120,6 @@ enum {
RTE_ACL_MIN_PRIORITY = 0,
};
-#define RTE_ACL_INVALID_USERDATA 0
-
#define RTE_ACL_MASKLEN_TO_BITMASK(v, s) \
((v) == 0 ? (v) : (typeof(v))((uint64_t)-1 << ((s) * CHAR_BIT - (v))))
diff --git a/lib/librte_table/rte_table_acl.c b/lib/librte_table/rte_table_acl.c
index 8f1f8ce..94b69a9 100644
--- a/lib/librte_table/rte_table_acl.c
+++ b/lib/librte_table/rte_table_acl.c
@@ -792,7 +792,7 @@ rte_table_acl_lookup(
pkts_mask &= ~pkt_mask;
- if (action_table_pos != RTE_ACL_INVALID_USERDATA) {
+ if (action_table_pos != 0) {
pkts_out_mask |= pkt_mask;
entries[pkt_pos] = (void *)
&acl->memory[action_table_pos *
--
2.10.2
^ permalink raw reply related
* [PATCH 03/13] rte_ether: set PKT_RX_VLAN_STRIPPED in rte_vlan_strip()
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_net/rte_ether.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
index ff3d065..26a8843 100644
--- a/lib/librte_net/rte_ether.h
+++ b/lib/librte_net/rte_ether.h
@@ -357,7 +357,7 @@ static inline int rte_vlan_strip(struct rte_mbuf *m)
return -1;
struct vlan_hdr *vh = (struct vlan_hdr *)(eh + 1);
- m->ol_flags |= PKT_RX_VLAN_PKT;
+ m->ol_flags |= PKT_RX_VLAN_PKT | PKT_RX_VLAN_STRIPPED;
m->vlan_tci = rte_be_to_cpu_16(vh->vlan_tci);
/* Copy ether header over rather than moving whole packet */
--
2.10.2
^ permalink raw reply related
* [PATCH 02/13] mbuf: rte_pktmbuf_free_bulk()
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_mbuf/rte_mbuf.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index ead7c6e..a95d99f 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -1248,6 +1248,21 @@ static inline void rte_pktmbuf_free(struct rte_mbuf *m)
}
/**
+ * Free multiple packet mbufs back into their original mempool(s).
+ *
+ * @param mp
+ * Pointer to array of packet mbufs to be freed.
+ * @param n
+ * Count of packet mbufs to free.
+ */
+static inline void rte_pktmbuf_free_bulk(struct rte_mbuf **mp, uint32_t n)
+{
+ uint32_t i;
+ for (i = 0; i < n; ++i)
+ rte_pktmbuf_free(mp[i]);
+}
+
+/**
* Creates a "clone" of the given packet mbuf.
*
* Walks through all segments of the given packet mbuf, and for each of them:
--
2.10.2
^ permalink raw reply related
* [PATCH 01/13] EAL: count nr_overcommit_hugepages as available
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
In-Reply-To: <cover.1481590851.git.mirq-linux@rere.qmqm.pl>
Signed-off-by: Michał Mirosław <michal.miroslaw@atendesoftware.pl>
---
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 43 ++++++++++++++++++-------
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c b/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
index 18858e2..f391e07 100644
--- a/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
+++ b/lib/librte_eal/linuxapp/eal/eal_hugepage_info.c
@@ -61,30 +61,38 @@
static const char sys_dir_path[] = "/sys/kernel/mm/hugepages";
+static int get_hp_sysfs_value(const char *subdir, const char *file, long unsigned *val)
+{
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof(path), "%s/%s/%s",
+ sys_dir_path, subdir, file);
+ return eal_parse_sysfs_value(path, val);
+}
+
/* this function is only called from eal_hugepage_info_init which itself
* is only called from a primary process */
static uint32_t
get_num_hugepages(const char *subdir)
{
- char path[PATH_MAX];
- long unsigned resv_pages, num_pages = 0;
+ long unsigned resv_pages, num_pages, over_pages, surplus_pages;
const char *nr_hp_file = "free_hugepages";
const char *nr_rsvd_file = "resv_hugepages";
+ const char *nr_over_file = "nr_overcommit_hugepages";
+ const char *nr_splus_file = "surplus_hugepages";
/* first, check how many reserved pages kernel reports */
- snprintf(path, sizeof(path), "%s/%s/%s",
- sys_dir_path, subdir, nr_rsvd_file);
- if (eal_parse_sysfs_value(path, &resv_pages) < 0)
+ if (get_hp_sysfs_value(subdir, nr_rsvd_file, &resv_pages) < 0)
return 0;
- snprintf(path, sizeof(path), "%s/%s/%s",
- sys_dir_path, subdir, nr_hp_file);
- if (eal_parse_sysfs_value(path, &num_pages) < 0)
+ if (get_hp_sysfs_value(subdir, nr_hp_file, &num_pages) < 0)
return 0;
- if (num_pages == 0)
- RTE_LOG(WARNING, EAL, "No free hugepages reported in %s\n",
- subdir);
+ if (get_hp_sysfs_value(subdir, nr_over_file, &over_pages) < 0)
+ over_pages = 0;
+
+ if (get_hp_sysfs_value(subdir, nr_splus_file, &surplus_pages) < 0)
+ surplus_pages = 0;
/* adjust num_pages */
if (num_pages >= resv_pages)
@@ -92,6 +100,19 @@ get_num_hugepages(const char *subdir)
else if (resv_pages)
num_pages = 0;
+ if (over_pages >= surplus_pages)
+ over_pages -= surplus_pages;
+ else
+ over_pages = 0;
+
+ if (num_pages == 0 && over_pages == 0)
+ RTE_LOG(WARNING, EAL, "No available hugepages reported in %s\n",
+ subdir);
+
+ num_pages += over_pages;
+ if (num_pages < over_pages) /* overflow */
+ num_pages = UINT32_MAX;
+
/* we want to return a uint32_t and more than this looks suspicious
* anyway ... */
if (num_pages > UINT32_MAX)
--
2.10.2
^ permalink raw reply related
* [PATCH 00/13] Fixes and tweaks
From: Michał Mirosław @ 2016-12-13 1:08 UTC (permalink / raw)
To: dev
This is a loose set of small fixes accumulated here at Atende Software
to be upstreamed. Please consider and apply each one separately.
Best Regards,
Michal Mirosław
---
Michał Mirosław (11):
EAL: count nr_overcommit_hugepages as available
mbuf: rte_pktmbuf_free_bulk()
rte_ether: set PKT_RX_VLAN_STRIPPED in rte_vlan_strip()
acl: allow zero verdict
acl: fix acl_flow_data comments
PMD/af_packet: guard against buffer overruns in RX path
PMD/af_packet: guard against buffer overruns in TX path
KNI: provided netif name's source is user-space
KNI: guard against unterminated dev_info.name leading to BUG in
alloc_netdev()
i40e: return -errno when intr setup fails
i40e: improve message grepability
Paweł Małachowski (1):
null: fake PMD capabilities
Piotr Bartosiewicz (1):
pcap: fix timestamps in output pcap file
drivers/net/af_packet/rte_eth_af_packet.c | 29 ++--
drivers/net/i40e/i40e_ethdev.c | 203 +++++++++---------------
drivers/net/null/rte_eth_null.c | 13 +-
drivers/net/pcap/rte_eth_pcap.c | 2 +-
lib/librte_acl/acl_run.h | 4 +-
lib/librte_acl/rte_acl.c | 3 +-
lib/librte_acl/rte_acl.h | 2 -
lib/librte_eal/linuxapp/eal/eal_hugepage_info.c | 43 +++--
lib/librte_eal/linuxapp/eal/eal_interrupts.c | 2 +-
lib/librte_eal/linuxapp/kni/kni_misc.c | 10 +-
lib/librte_mbuf/rte_mbuf.h | 15 ++
lib/librte_net/rte_ether.h | 2 +-
lib/librte_table/rte_table_acl.c | 2 +-
13 files changed, 169 insertions(+), 161 deletions(-)
--
2.10.2
^ permalink raw reply
* Re: [PATCH] SDK: Add scripts to initialize DPDK runtime
From: Jay Rolette @ 2016-12-12 23:41 UTC (permalink / raw)
To: Bruce Richardson; +Cc: Luca Boccassi, DPDK, Christian Ehrhardt
In-Reply-To: <20161212211222.GA50316@bricha3-MOBL3.ger.corp.intel.com>
On Mon, Dec 12, 2016 at 3:12 PM, Bruce Richardson <
bruce.richardson@intel.com> wrote:
> On Mon, Dec 12, 2016 at 07:24:02PM +0000, Luca Boccassi wrote:
> > From: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> >
> > A tools/init directory is added with dpdk-init, a script that can be
> > used to initialize a DPDK runtime environment. 2 config files with
> > default options, dpdk.conf and interfaces, are provided as well
> > together with a SysV init script and a systemd service unit.
> >
> > Signed-off-by: Luca Boccassi <lboccass@brocade.com>
> > Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> > ---
> <snip>
> > new file mode 100755
> > index 0000000..89e0399
> > --- /dev/null
> > +++ b/tools/init/dpdk-init.in
> > @@ -0,0 +1,256 @@
> > +#!/bin/sh
> > +#
> > +# dpdk-init: startup script to initialize a dpdk runtime environment
> > +#
> > +# Copyright 2015-2016 Canonical Ltd.
> > +# Autor: Stefan Bader <stefan.bader@canonical.com>
> > +# Autor: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> > +#
> > +# This program is free software: you can redistribute it and/or
> modify
> > +# it under the terms of the GNU General Public License version 3,
> > +# as published by the Free Software Foundation.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > +# GNU General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU General Public License
> > +# along with this program. If not, see <
> http://www.gnu.org/licenses/>.
> > +#
>
> Any particular reason this is licensed under GPL v3. AFAIK, all the
> userspace code in DPDK is licensed under a BSD license (with the
> exception of some dual licensed stuff which is shared between kernel and
> userspace). I just worry that adding additional licenses into the mix
> may confuse things.
>
> Regards,
> /Bruce
>
Most generally, shouldn't any patch that isn't compatible with the standard
DPDK license be rejected? With the specific exception for the KNI kernel
bits that require different licenses...
Jay
^ permalink raw reply
* Re: [PATCH v4] net/kni: add KNI PMD
From: Yong Wang @ 2016-12-12 21:59 UTC (permalink / raw)
To: Ferruh Yigit, dev@dpdk.org
In-Reply-To: <20161130181228.25380-1-ferruh.yigit@intel.com>
> -----Original Message-----
> From: Ferruh Yigit [mailto:ferruh.yigit@intel.com]
> Sent: Wednesday, November 30, 2016 10:12 AM
> To: dev@dpdk.org
> Cc: Ferruh Yigit <ferruh.yigit@intel.com>; Yong Wang
> <yongwang@vmware.com>
> Subject: [PATCH v4] net/kni: add KNI PMD
>
> Add KNI PMD which wraps librte_kni for ease of use.
>
> KNI PMD can be used as any regular PMD to send / receive packets to the
> Linux networking stack.
>
> Signed-off-by: Ferruh Yigit <ferruh.yigit@intel.com>
> ---
>
> v4:
> * allow only single queue
> * use driver.name as name
>
> v3:
> * rebase on top of latest master
>
> v2:
> * updated driver name eth_kni -> net_kni
> ---
> config/common_base | 1 +
> config/common_linuxapp | 1 +
> drivers/net/Makefile | 1 +
> drivers/net/kni/Makefile | 63 +++++
> drivers/net/kni/rte_eth_kni.c | 462
> ++++++++++++++++++++++++++++++++
> drivers/net/kni/rte_pmd_kni_version.map | 4 +
> mk/rte.app.mk | 10 +-
> 7 files changed, 537 insertions(+), 5 deletions(-)
> create mode 100644 drivers/net/kni/Makefile
> create mode 100644 drivers/net/kni/rte_eth_kni.c
> create mode 100644 drivers/net/kni/rte_pmd_kni_version.map
>
> diff --git a/config/common_base b/config/common_base
> index 4bff83a..3385879 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -543,6 +543,7 @@ CONFIG_RTE_PIPELINE_STATS_COLLECT=n
> # Compile librte_kni
> #
> CONFIG_RTE_LIBRTE_KNI=n
> +CONFIG_RTE_LIBRTE_PMD_KNI=n
> CONFIG_RTE_KNI_KMOD=n
> CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
> CONFIG_RTE_KNI_VHOST=n
> diff --git a/config/common_linuxapp b/config/common_linuxapp
> index 2483dfa..2ecd510 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -39,6 +39,7 @@ CONFIG_RTE_EAL_IGB_UIO=y
> CONFIG_RTE_EAL_VFIO=y
> CONFIG_RTE_KNI_KMOD=y
> CONFIG_RTE_LIBRTE_KNI=y
> +CONFIG_RTE_LIBRTE_PMD_KNI=y
> CONFIG_RTE_LIBRTE_VHOST=y
> CONFIG_RTE_LIBRTE_PMD_VHOST=y
> CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index bc93230..c4771cd 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -41,6 +41,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic
> DIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k
> DIRS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e
> DIRS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += kni
> DIRS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += mlx4
> DIRS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5
> DIRS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += mpipe
> diff --git a/drivers/net/kni/Makefile b/drivers/net/kni/Makefile
> new file mode 100644
> index 0000000..0b7cf91
> --- /dev/null
> +++ b/drivers/net/kni/Makefile
> @@ -0,0 +1,63 @@
> +# BSD LICENSE
> +#
> +# Copyright(c) 2016 Intel Corporation. All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# * Redistributions of source code must retain the above copyright
> +# notice, this list of conditions and the following disclaimer.
> +# * Redistributions in binary form must reproduce the above copyright
> +# notice, this list of conditions and the following disclaimer in
> +# the documentation and/or other materials provided with the
> +# distribution.
> +# * Neither the name of Intel Corporation nor the names of its
> +# contributors may be used to endorse or promote products derived
> +# from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_kni.a
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +LDLIBS += -lpthread
> +
> +EXPORT_MAP := rte_pmd_kni_version.map
> +
> +LIBABIVER := 1
> +
> +#
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += rte_eth_kni.c
> +
> +#
> +# Export include files
> +#
> +SYMLINK-y-include +=
> +
> +# this lib depends upon:
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += lib/librte_eal
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += lib/librte_kni
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += lib/librte_mbuf
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += lib/librte_mempool
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/kni/rte_eth_kni.c b/drivers/net/kni/rte_eth_kni.c
> new file mode 100644
> index 0000000..6c4df96
> --- /dev/null
> +++ b/drivers/net/kni/rte_eth_kni.c
> @@ -0,0 +1,462 @@
> +/*-
> + * BSD LICENSE
> + *
> + * Copyright(c) 2016 Intel Corporation. All rights reserved.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in
> + * the documentation and/or other materials provided with the
> + * distribution.
> + * * Neither the name of Intel Corporation nor the names of its
> + * contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
> THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> DAMAGE.
> + */
> +
> +#include <fcntl.h>
> +#include <pthread.h>
> +#include <unistd.h>
> +
> +#include <rte_ethdev.h>
> +#include <rte_kni.h>
> +#include <rte_malloc.h>
> +#include <rte_vdev.h>
> +
> +/* Only single queue supported */
> +#define KNI_MAX_QUEUE_PER_PORT 1
> +
> +#define MAX_PACKET_SZ 2048
> +#define MAX_KNI_PORTS 8
> +
> +struct pmd_queue_stats {
> + uint64_t pkts;
> + uint64_t bytes;
> + uint64_t err_pkts;
> +};
> +
> +struct pmd_queue {
> + struct pmd_internals *internals;
> + struct rte_mempool *mb_pool;
> +
> + struct pmd_queue_stats rx;
> + struct pmd_queue_stats tx;
> +};
> +
> +struct pmd_internals {
> + struct rte_kni *kni;
> + int is_kni_started;
> +
> + pthread_t thread;
> + int stop_thread;
> +
> + struct pmd_queue rx_queues[KNI_MAX_QUEUE_PER_PORT];
> + struct pmd_queue tx_queues[KNI_MAX_QUEUE_PER_PORT];
> +};
> +
> +static struct ether_addr eth_addr;
> +static struct rte_eth_link pmd_link = {
> + .link_speed = ETH_SPEED_NUM_10G,
> + .link_duplex = ETH_LINK_FULL_DUPLEX,
> + .link_status = 0
> +};
> +static int is_kni_initialized;
> +
> +static uint16_t
> +eth_kni_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> + struct pmd_queue *kni_q = q;
> + struct rte_kni *kni = kni_q->internals->kni;
> + uint16_t nb_pkts;
> +
> + nb_pkts = rte_kni_rx_burst(kni, bufs, nb_bufs);
> +
> + kni_q->rx.pkts += nb_pkts;
> + kni_q->rx.err_pkts += nb_bufs - nb_pkts;
> +
> + return nb_pkts;
> +}
> +
> +static uint16_t
> +eth_kni_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
> +{
> + struct pmd_queue *kni_q = q;
> + struct rte_kni *kni = kni_q->internals->kni;
> + uint16_t nb_pkts;
> +
> + nb_pkts = rte_kni_tx_burst(kni, bufs, nb_bufs);
> +
> + kni_q->tx.pkts += nb_pkts;
> + kni_q->tx.err_pkts += nb_bufs - nb_pkts;
> +
> + return nb_pkts;
> +}
> +
> +static void *
> +kni_handle_request(void *param)
> +{
> + struct pmd_internals *internals = param;
> +#define MS 1000
> +
> + while (!internals->stop_thread) {
> + rte_kni_handle_request(internals->kni);
> + usleep(500 * MS);
> + }
> +
> + return param;
> +}
> +
Do we really need a thread to handle request by default? I know there are apps that handle request their own way and having a separate thread could add synchronization problems. Can we at least add an option to disable this?
> +static int
> +eth_kni_start(struct rte_eth_dev *dev)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + uint16_t port_id = dev->data->port_id;
> + struct rte_mempool *mb_pool;
> + struct rte_kni_conf conf;
> + const char *name = dev->data->name + 4; /* remove net_ */
> +
> + snprintf(conf.name, RTE_KNI_NAMESIZE, "%s", name);
> + conf.force_bind = 0;
> + conf.group_id = port_id;
> + conf.mbuf_size = MAX_PACKET_SZ;
> + mb_pool = internals->rx_queues[0].mb_pool;
> +
> + internals->kni = rte_kni_alloc(mb_pool, &conf, NULL);
> + if (internals->kni == NULL) {
> + RTE_LOG(ERR, PMD,
> + "Fail to create kni for port: %d\n", port_id);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +eth_kni_dev_start(struct rte_eth_dev *dev)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + int ret;
> +
> + if (internals->is_kni_started == 0) {
> + ret = eth_kni_start(dev);
> + if (ret)
> + return -1;
> + internals->is_kni_started = 1;
> + }
> +
In case is_kni_started is 1 already, shouldn't we return directly instead of proceeding?
> + ret = pthread_create(&internals->thread, NULL, kni_handle_request,
> + internals);
> + if (ret) {
> + RTE_LOG(ERR, PMD, "Fail to create kni request thread\n");
> + return -1;
> + }
> +
> + dev->data->dev_link.link_status = 1;
> +
> + return 0;
> +}
> +
> +static void
> +eth_kni_dev_stop(struct rte_eth_dev *dev)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + int ret;
> +
> + internals->stop_thread = 1;
> +
> + ret = pthread_cancel(internals->thread);
> + if (ret)
> + RTE_LOG(ERR, PMD, "Can't cancel the thread\n");
> +
> + ret = pthread_join(internals->thread, NULL);
> + if (ret)
> + RTE_LOG(ERR, PMD, "Can't join the thread\n");
> +
> + internals->stop_thread = 0;
> +
> + dev->data->dev_link.link_status = 0;
> +}
> +
> +static int
> +eth_kni_dev_configure(struct rte_eth_dev *dev __rte_unused)
> +{
> + return 0;
> +}
> +
> +static void
> +eth_kni_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info
> *dev_info)
> +{
> + struct rte_eth_dev_data *data = dev->data;
> +
> + dev_info->driver_name = data->drv_name;
> + dev_info->max_mac_addrs = 1;
> + dev_info->max_rx_pktlen = (uint32_t)-1;
> + dev_info->max_rx_queues = KNI_MAX_QUEUE_PER_PORT;
> + dev_info->max_tx_queues = KNI_MAX_QUEUE_PER_PORT;
> + dev_info->min_rx_bufsize = 0;
> + dev_info->pci_dev = NULL;
> +}
> +
> +static int
> +eth_kni_rx_queue_setup(struct rte_eth_dev *dev,
> + uint16_t rx_queue_id,
> + uint16_t nb_rx_desc __rte_unused,
> + unsigned int socket_id __rte_unused,
> + const struct rte_eth_rxconf *rx_conf __rte_unused,
> + struct rte_mempool *mb_pool)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + struct pmd_queue *q;
> +
> + q = &internals->rx_queues[rx_queue_id];
> + q->internals = internals;
> + q->mb_pool = mb_pool;
> +
> + dev->data->rx_queues[rx_queue_id] = q;
> +
> + return 0;
> +}
> +
> +static int
> +eth_kni_tx_queue_setup(struct rte_eth_dev *dev,
> + uint16_t tx_queue_id,
> + uint16_t nb_tx_desc __rte_unused,
> + unsigned int socket_id __rte_unused,
> + const struct rte_eth_txconf *tx_conf __rte_unused)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + struct pmd_queue *q;
> +
> + q = &internals->tx_queues[tx_queue_id];
> + q->internals = internals;
> +
> + dev->data->tx_queues[tx_queue_id] = q;
> +
> + return 0;
> +}
> +
> +static void
> +eth_kni_queue_release(void *q __rte_unused)
> +{
> +}
> +
> +static int
> +eth_kni_link_update(struct rte_eth_dev *dev __rte_unused,
> + int wait_to_complete __rte_unused)
> +{
> + return 0;
> +}
> +
> +static void
> +eth_kni_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
> +{
> + unsigned long rx_packets_total = 0, rx_bytes_total = 0;
> + unsigned long tx_packets_total = 0, tx_bytes_total = 0;
> + struct rte_eth_dev_data *data = dev->data;
> + unsigned long tx_packets_err_total = 0;
> + unsigned int i, num_stats;
> + struct pmd_queue *q;
> +
> + num_stats = RTE_MIN((unsigned
> int)RTE_ETHDEV_QUEUE_STAT_CNTRS,
> + data->nb_rx_queues);
> + for (i = 0; i < num_stats; i++) {
> + q = data->rx_queues[i];
> + stats->q_ipackets[i] = q->rx.pkts;
> + stats->q_ibytes[i] = q->rx.bytes;
> + rx_packets_total += stats->q_ipackets[i];
> + rx_bytes_total += stats->q_ibytes[i];
> + }
> +
> + num_stats = RTE_MIN((unsigned
> int)RTE_ETHDEV_QUEUE_STAT_CNTRS,
> + data->nb_tx_queues);
> + for (i = 0; i < num_stats; i++) {
> + q = data->tx_queues[i];
> + stats->q_opackets[i] = q->tx.pkts;
> + stats->q_obytes[i] = q->tx.bytes;
> + stats->q_errors[i] = q->tx.err_pkts;
> + tx_packets_total += stats->q_opackets[i];
> + tx_bytes_total += stats->q_obytes[i];
> + tx_packets_err_total += stats->q_errors[i];
> + }
> +
> + stats->ipackets = rx_packets_total;
> + stats->ibytes = rx_bytes_total;
> + stats->opackets = tx_packets_total;
> + stats->obytes = tx_bytes_total;
> + stats->oerrors = tx_packets_err_total;
> +}
> +
> +static void
> +eth_kni_stats_reset(struct rte_eth_dev *dev)
> +{
> + struct rte_eth_dev_data *data = dev->data;
> + struct pmd_queue *q;
> + unsigned int i;
> +
> + for (i = 0; i < data->nb_rx_queues; i++) {
> + q = data->rx_queues[i];
> + q->rx.pkts = 0;
> + q->rx.bytes = 0;
> + }
> + for (i = 0; i < data->nb_tx_queues; i++) {
> + q = data->tx_queues[i];
> + q->tx.pkts = 0;
> + q->tx.bytes = 0;
> + q->tx.err_pkts = 0;
> + }
> +}
> +
> +static const struct eth_dev_ops eth_kni_ops = {
> + .dev_start = eth_kni_dev_start,
> + .dev_stop = eth_kni_dev_stop,
> + .dev_configure = eth_kni_dev_configure,
> + .dev_infos_get = eth_kni_dev_info,
> + .rx_queue_setup = eth_kni_rx_queue_setup,
> + .tx_queue_setup = eth_kni_tx_queue_setup,
> + .rx_queue_release = eth_kni_queue_release,
> + .tx_queue_release = eth_kni_queue_release,
> + .link_update = eth_kni_link_update,
> + .stats_get = eth_kni_stats_get,
> + .stats_reset = eth_kni_stats_reset,
> +};
> +
> +static struct rte_vdev_driver eth_kni_drv;
> +
> +static struct rte_eth_dev *
> +eth_kni_create(const char *name, unsigned int numa_node)
> +{
> + struct pmd_internals *internals = NULL;
> + struct rte_eth_dev_data *data;
> + struct rte_eth_dev *eth_dev;
> +
> + RTE_LOG(INFO, PMD, "Creating kni ethdev on numa socket %u\n",
> + numa_node);
> +
> + data = rte_zmalloc_socket(name, sizeof(*data), 0, numa_node);
> + if (data == NULL)
> + goto error;
> +
> + internals = rte_zmalloc_socket(name, sizeof(*internals), 0,
> numa_node);
> + if (internals == NULL)
> + goto error;
> +
> + /* reserve an ethdev entry */
> + eth_dev = rte_eth_dev_allocate(name);
> + if (eth_dev == NULL)
> + goto error;
> +
> + data->dev_private = internals;
> + data->port_id = eth_dev->data->port_id;
> + memmove(data->name, eth_dev->data->name, sizeof(data-
> >name));
> + data->nb_rx_queues = 1;
> + data->nb_tx_queues = 1;
> + data->dev_link = pmd_link;
> + data->mac_addrs = ð_addr;
> +
> + eth_dev->data = data;
> + eth_dev->dev_ops = ð_kni_ops;
> + eth_dev->driver = NULL;
> +
> + data->dev_flags = RTE_ETH_DEV_DETACHABLE;
> + data->kdrv = RTE_KDRV_NONE;
> + data->drv_name = eth_kni_drv.driver.name;
> + data->numa_node = numa_node;
> +
> + return eth_dev;
> +
> +error:
> + rte_free(data);
> + rte_free(internals);
> +
> + return NULL;
> +}
> +
> +static int
> +kni_init(void)
> +{
> + if (is_kni_initialized == 0)
> + rte_kni_init(MAX_KNI_PORTS);
> +
> + is_kni_initialized += 1;
> +
> + return 0;
> +}
> +
> +static int
> +eth_kni_probe(const char *name, const char *params __rte_unused)
> +{
> + struct rte_eth_dev *eth_dev;
> + int ret;
> +
> + RTE_LOG(INFO, PMD, "Initializing eth_kni for %s\n", name);
> +
> + ret = kni_init();
> + if (ret < 0)
> + /* Not return error to prevent panic in rte_eal_init() */
> + return 0;
If we don't return error here, the application that needs to add KNI ports eventually will fail. If it's a fail-stop situation, isn't it better to return error where the it happened?
> + eth_dev = eth_kni_create(name, rte_socket_id());
> + if (eth_dev == NULL)
> + return -1;
> +
> + eth_dev->rx_pkt_burst = eth_kni_rx;
> + eth_dev->tx_pkt_burst = eth_kni_tx;
> +
> + return 0;
> +}
> +
> +static int
> +eth_kni_remove(const char *name)
> +{
> + struct rte_eth_dev *eth_dev;
> + struct pmd_internals *internals;
> +
> + RTE_LOG(INFO, PMD, "Un-Initializing eth_kni for %s\n", name);
> +
> + /* find the ethdev entry */
> + eth_dev = rte_eth_dev_allocated(name);
> + if (eth_dev == NULL)
> + return -1;
> +
> + eth_kni_dev_stop(eth_dev);
> +
> + if (eth_dev->data) {
> + internals = eth_dev->data->dev_private;
> + rte_kni_release(internals->kni);
> +
> + rte_free(internals);
> + }
> + rte_free(eth_dev->data);
> +
> + rte_eth_dev_release_port(eth_dev);
> +
> + is_kni_initialized -= 1;
> + if (is_kni_initialized == 0)
> + rte_kni_close();
> +
> + return 0;
> +}
> +
> +static struct rte_vdev_driver eth_kni_drv = {
> + .probe = eth_kni_probe,
> + .remove = eth_kni_remove,
> +};
> +
> +RTE_PMD_REGISTER_VDEV(net_kni, eth_kni_drv);
> diff --git a/drivers/net/kni/rte_pmd_kni_version.map
> b/drivers/net/kni/rte_pmd_kni_version.map
> new file mode 100644
> index 0000000..31eca32
> --- /dev/null
> +++ b/drivers/net/kni/rte_pmd_kni_version.map
> @@ -0,0 +1,4 @@
> +DPDK_17.02 {
> +
> + local: *;
> +};
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index f75f0e2..af02816 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -59,11 +59,6 @@ _LDLIBS-y += -L$(RTE_SDK_BIN)/lib
> #
> # Order is important: from higher level to lower level
> #
> -
> -ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
> -_LDLIBS-$(CONFIG_RTE_LIBRTE_KNI) += -lrte_kni
> -endif
> -
> _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE) += -lrte_pipeline
> _LDLIBS-$(CONFIG_RTE_LIBRTE_TABLE) += -lrte_table
> _LDLIBS-$(CONFIG_RTE_LIBRTE_PORT) += -lrte_port
> @@ -84,6 +79,10 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_POWER) += -
> lrte_power
>
> _LDLIBS-y += --whole-archive
>
> +ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_KNI) += -lrte_kni
> +endif
> +
> _LDLIBS-$(CONFIG_RTE_LIBRTE_TIMER) += -lrte_timer
> _LDLIBS-$(CONFIG_RTE_LIBRTE_HASH) += -lrte_hash
> _LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lrte_vhost
> @@ -115,6 +114,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += -
> lrte_pmd_enic
> _LDLIBS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += -lrte_pmd_fm10k
> _LDLIBS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += -lrte_pmd_i40e
> _LDLIBS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += -lrte_pmd_ixgbe
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += -lrte_pmd_kni
> _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD) += -lrte_pmd_mlx4 -
> libverbs
> _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += -lrte_pmd_mlx5 -
> libverbs
> _LDLIBS-$(CONFIG_RTE_LIBRTE_MPIPE_PMD) += -lrte_pmd_mpipe -lgxio
> --
> 2.9.3
^ permalink raw reply
* Re: [PATCH] SDK: Add scripts to initialize DPDK runtime
From: Luca Boccassi @ 2016-12-12 21:58 UTC (permalink / raw)
To: bruce.richardson@intel.com
Cc: christian.ehrhardt@canonical.com, dev@dpdk.org,
stefan.bader@canonical.com
In-Reply-To: <20161212211222.GA50316@bricha3-MOBL3.ger.corp.intel.com>
On Mon, 2016-12-12 at 21:12 +0000, Bruce Richardson wrote:
> On Mon, Dec 12, 2016 at 07:24:02PM +0000, Luca Boccassi wrote:
> > From: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> >
> > A tools/init directory is added with dpdk-init, a script that can be
> > used to initialize a DPDK runtime environment. 2 config files with
> > default options, dpdk.conf and interfaces, are provided as well
> > together with a SysV init script and a systemd service unit.
> >
> > Signed-off-by: Luca Boccassi <lboccass@brocade.com>
> > Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> > ---
> <snip>
> > new file mode 100755
> > index 0000000..89e0399
> > --- /dev/null
> > +++ b/tools/init/dpdk-init.in
> > @@ -0,0 +1,256 @@
> > +#!/bin/sh
> > +#
> > +# dpdk-init: startup script to initialize a dpdk runtime environment
> > +#
> > +# Copyright 2015-2016 Canonical Ltd.
> > +# Autor: Stefan Bader <stefan.bader@canonical.com>
> > +# Autor: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> > +#
> > +# This program is free software: you can redistribute it and/or modify
> > +# it under the terms of the GNU General Public License version 3,
> > +# as published by the Free Software Foundation.
> > +#
> > +# This program is distributed in the hope that it will be useful,
> > +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > +# GNU General Public License for more details.
> > +#
> > +# You should have received a copy of the GNU General Public License
> > +# along with this program. If not, see <https://urldefense.proofpoint.com/v2/url?u=http-3A__www.gnu.org_licenses_&d=DgIBAg&c=IL_XqQWOjubgfqINi2jTzg&r=QTEM8ICX7t_SLgWP3qPWtKiwKMps487LPWQx-B9AqIc&m=DJ24ssai2FzyX2jctmeGTqSlmXniJb0K-CfYJmCvhCI&s=Ovj9NdvIvL-I0pPSRrQ3fGw2twwaW7GO_vOpclVZ2FU&e= >.
> > +#
>
> Any particular reason this is licensed under GPL v3. AFAIK, all the
> userspace code in DPDK is licensed under a BSD license (with the
> exception of some dual licensed stuff which is shared between kernel and
> userspace). I just worry that adding additional licenses into the mix
> may confuse things.
>
> Regards,
> /Bruce
If the 2 authors (CC'ed Stefan, the second one) agree and give
permission it could be relicensed to BSD.
Stefan, Christian, is that OK for you?
--
Kind regards,
Luca Boccassi
^ permalink raw reply
* Re: [PATCH] SDK: Add scripts to initialize DPDK runtime
From: Bruce Richardson @ 2016-12-12 21:12 UTC (permalink / raw)
To: Luca Boccassi; +Cc: dev, Christian Ehrhardt
In-Reply-To: <1481570642-15138-1-git-send-email-lboccass@brocade.com>
On Mon, Dec 12, 2016 at 07:24:02PM +0000, Luca Boccassi wrote:
> From: Christian Ehrhardt <christian.ehrhardt@canonical.com>
>
> A tools/init directory is added with dpdk-init, a script that can be
> used to initialize a DPDK runtime environment. 2 config files with
> default options, dpdk.conf and interfaces, are provided as well
> together with a SysV init script and a systemd service unit.
>
> Signed-off-by: Luca Boccassi <lboccass@brocade.com>
> Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> ---
<snip>
> new file mode 100755
> index 0000000..89e0399
> --- /dev/null
> +++ b/tools/init/dpdk-init.in
> @@ -0,0 +1,256 @@
> +#!/bin/sh
> +#
> +# dpdk-init: startup script to initialize a dpdk runtime environment
> +#
> +# Copyright 2015-2016 Canonical Ltd.
> +# Autor: Stefan Bader <stefan.bader@canonical.com>
> +# Autor: Christian Ehrhardt <christian.ehrhardt@canonical.com>
> +#
> +# This program is free software: you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License version 3,
> +# as published by the Free Software Foundation.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +#
Any particular reason this is licensed under GPL v3. AFAIK, all the
userspace code in DPDK is licensed under a BSD license (with the
exception of some dual licensed stuff which is shared between kernel and
userspace). I just worry that adding additional licenses into the mix
may confuse things.
Regards,
/Bruce
^ permalink raw reply
* Re: [PATCH v12] net/tap: new TUN/TAP device PMD
From: Wiles, Keith @ 2016-12-12 21:09 UTC (permalink / raw)
To: Marc; +Cc: dev@dpdk.org
In-Reply-To: <CAExC=0R7MXQZVeCAq198P5ubRtPnPJhqCA0fUqL-dBFQksuUog@mail.gmail.com>
> On Dec 12, 2016, at 1:13 PM, Marc <marcdevel@gmail.com> wrote:
>
> Keith,
>
> A bit late, but two very high level questions. Do you have performance numbers compared to KNI? Did you consider using AF_PACKET PACKET_MMAP which could potentially reduce the number of syscalls to 1 for RX and TX of a burst?
Hi Marc,
I was not trying to create a high performance interface, just a Tap interface to use standard applications and calls to send/receive traffic to the DPDK application. I did not expect other then some management like interface in the application would use the Tap PMD.
>
> Marc
>
> On 12 December 2016 at 15:38, Keith Wiles <keith.wiles@intel.com> wrote:
> The PMD allows for DPDK and the host to communicate using a raw
> device interface on the host and in the DPDK application. The device
> created is a Tap device with a L2 packet header.
>
> v12- Fixup minor changes for driver_name and version number
> v11- Add the tap.rst to the nic/index.rst file
> v10- Change the string name used to allow for multiple devices.
> v9 - Fix up the docs to use correct syntax
> v8 - Fix issue with tap_tx_queue_setup() not return zero on success.
> v7 - Reword the comment in common_base and fix the data->name issue
> v6 - fixed the checkpatch issues
> v5 - merge in changes from list review see related emails
> fixed many minor edits
> v4 - merge with latest driver changes
> v3 - fix includes by removing ifdef for other type besides Linux
> Fix the copyright notice in the Makefile
> v2 - merge all of the patches into one patch
> Fix a typo on naming the tap device
> Update the maintainers list
>
> Signed-off-by: Keith Wiles <keith.wiles@intel.com>
> ---
> MAINTAINERS | 5 +
> config/common_base | 9 +
> config/common_linuxapp | 1 +
> doc/guides/nics/index.rst | 1 +
> doc/guides/nics/tap.rst | 136 ++++++
> drivers/net/Makefile | 1 +
> drivers/net/tap/Makefile | 57 +++
> drivers/net/tap/rte_eth_tap.c | 765 ++++++++++++++++++++++++++++++++
> drivers/net/tap/rte_pmd_tap_version.map | 4 +
> mk/rte.app.mk | 1 +
> 10 files changed, 980 insertions(+)
> create mode 100644 doc/guides/nics/tap.rst
> create mode 100644 drivers/net/tap/Makefile
> create mode 100644 drivers/net/tap/rte_eth_tap.c
> create mode 100644 drivers/net/tap/rte_pmd_tap_version.map
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 26d9590..842fb6d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -398,6 +398,11 @@ F: doc/guides/nics/pcap_ring.rst
> F: app/test/test_pmd_ring.c
> F: app/test/test_pmd_ring_perf.c
>
> +Tap PMD
> +M: Keith Wiles <keith.wiles@intel.com>
> +F: drivers/net/tap
> +F: doc/guides/nics/tap.rst
> +
> Null Networking PMD
> M: Tetsuya Mukawa <mtetsuyah@gmail.com>
> F: drivers/net/null/
> diff --git a/config/common_base b/config/common_base
> index 652a839..eb51cdb 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -590,3 +590,12 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n
> CONFIG_RTE_TEST_PMD=y
> CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n
> CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n
> +
> +#
> +# Compile the TAP PMD
> +#
> +# The TAP PMD is currently only built for Linux and the
> +# option is enabled by default in common_linuxapp file,
> +# set to 'n' in the common_base file.
> +#
> +CONFIG_RTE_LIBRTE_PMD_TAP=n
> diff --git a/config/common_linuxapp b/config/common_linuxapp
> index 2483dfa..782b503 100644
> --- a/config/common_linuxapp
> +++ b/config/common_linuxapp
> @@ -44,3 +44,4 @@ CONFIG_RTE_LIBRTE_PMD_VHOST=y
> CONFIG_RTE_LIBRTE_PMD_AF_PACKET=y
> CONFIG_RTE_LIBRTE_POWER=y
> CONFIG_RTE_VIRTIO_USER=y
> +CONFIG_RTE_LIBRTE_PMD_TAP=y
> diff --git a/doc/guides/nics/index.rst b/doc/guides/nics/index.rst
> index 92d56a5..af92529 100644
> --- a/doc/guides/nics/index.rst
> +++ b/doc/guides/nics/index.rst
> @@ -51,6 +51,7 @@ Network Interface Controller Drivers
> nfp
> qede
> szedata2
> + tap
> thunderx
> virtio
> vhost
> diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst
> new file mode 100644
> index 0000000..622b9e7
> --- /dev/null
> +++ b/doc/guides/nics/tap.rst
> @@ -0,0 +1,136 @@
> +.. BSD LICENSE
> + Copyright(c) 2016 Intel Corporation. All rights reserved.
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions
> + are met:
> +
> + * Redistributions of source code must retain the above copyright
> + notice, this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in
> + the documentation and/or other materials provided with the
> + distribution.
> + * Neither the name of Intel Corporation nor the names of its
> + contributors may be used to endorse or promote products derived
> + from this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +Tun/Tap Poll Mode Driver
> +========================
> +
> +The ``rte_eth_tap.c`` PMD creates a device using TUN/TAP interfaces on the
> +local host. The PMD allows for DPDK and the host to communicate using a raw
> +device interface on the host and in the DPDK application.
> +
> +The device created is a TAP device, which sends/receives packet in a raw
> +format with a L2 header. The usage for a TAP PMD is for connectivity to the
> +local host using a TAP interface. When the TAP PMD is initialized it will
> +create a number of tap devices in the host accessed via ``ifconfig -a`` or
> +``ip`` command. The commands can be used to assign and query the virtual like
> +device.
> +
> +These TAP interfaces can be used with Wireshark or tcpdump or Pktgen-DPDK
> +along with being able to be used as a network connection to the DPDK
> +application. The method enable one or more interfaces is to use the
> +``--vdev=net_tap`` option on the DPDK application command line. Each
> +``--vdev=net_tap`` option give will create an interface named dtap0, dtap1,
> +and so on.
> +
> +The interfaced name can be changed by adding the ``iface=foo0``, for example::
> +
> + --vdev=net_tap,iface=foo0 --vdev=net_tap,iface=foo1, ...
> +
> +Also the speed of the interface can be changed from 10G to whatever number
> +needed, but the interface does not enforce that speed, for example::
> +
> + --vdev=net_tap,iface=foo0,speed=25000
> +
> +After the DPDK application is started you can send and receive packets on the
> +interface using the standard rx_burst/tx_burst APIs in DPDK. From the host
> +point of view you can use any host tool like tcpdump, Wireshark, ping, Pktgen
> +and others to communicate with the DPDK application. The DPDK application may
> +not understand network protocols like IPv4/6, UDP or TCP unless the
> +application has been written to understand these protocols.
> +
> +If you need the interface as a real network interface meaning running and has
> +a valid IP address then you can do this with the following commands::
> +
> + sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
> + sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
> +
> +Please change the IP addresses as you see fit.
> +
> +If routing is enabled on the host you can also communicate with the DPDK App
> +over the internet via a standard socket layer application as long as you
> +account for the protocol handing in the application.
> +
> +If you have a Network Stack in your DPDK application or something like it you
> +can utilize that stack to handle the network protocols. Plus you would be able
> +to address the interface using an IP address assigned to the internal
> +interface.
> +
> +Example
> +-------
> +
> +The following is a simple example of using the TUN/TAP PMD with the Pktgen
> +packet generator. It requires that the ``socat`` utility is installed on the
> +test system.
> +
> +Build DPDK, then pull down Pktgen and build pktgen using the DPDK SDK/Target
> +used to build the dpdk you pulled down.
> +
> +Run pktgen from the pktgen directory in a terminal with a commandline like the
> +following::
> +
> + sudo ./app/app/x86_64-native-linuxapp-gcc/app/pktgen -l 1-5 -n 4 \
> + --proc-type auto --log-level 8 --socket-mem 512,512 --file-prefix pg \
> + --vdev=net_tap --vdev=net_tap -b 05:00.0 -b 05:00.1 \
> + -b 04:00.0 -b 04:00.1 -b 04:00.2 -b 04:00.3 \
> + -b 81:00.0 -b 81:00.1 -b 81:00.2 -b 81:00.3 \
> + -b 82:00.0 -b 83:00.0 -- -T -P -m [2:3].0 -m [4:5].1 \
> + -f themes/black-yellow.theme
> +
> +.. Note:
> +
> + Change the ``-b`` options to blacklist all of your physical ports. The
> + following command line is all one line.
> +
> + Also, ``-f themes/black-yellow.theme`` is optional if the default colors
> + work on your system configuration. See the Pktgen docs for more
> + information.
> +
> +Verify with ``ifconfig -a`` command in a different xterm window, should have a
> +``dtap0`` and ``dtap1`` interfaces created.
> +
> +Next set the links for the two interfaces to up via the commands below::
> +
> + sudo ip link set dtap0 up; sudo ip addr add 192.168.0.250/24 dev dtap0
> + sudo ip link set dtap1 up; sudo ip addr add 192.168.1.250/24 dev dtap1
> +
> +Then use socat to create a loopback for the two interfaces::
> +
> + sudo socat interface:dtap0 interface:dtap1
> +
> +Then on the Pktgen command line interface you can start sending packets using
> +the commands ``start 0`` and ``start 1`` or you can start both at the same
> +time with ``start all``. The command ``str`` is an alias for ``start all`` and
> +``stp`` is an alias for ``stop all``.
> +
> +While running you should see the 64 byte counters increasing to verify the
> +traffic is being looped back. You can use ``set all size XXX`` to change the
> +size of the packets after you stop the traffic. Use the pktgen ``help``
> +command to see a list of all commands. You can also use the ``-f`` option to
> +load commands at startup.
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index bc93230..e366a85 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
> DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
> DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
> DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2
> +DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
> DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
> DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
> DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
> diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile
> new file mode 100644
> index 0000000..e18f30c
> --- /dev/null
> +++ b/drivers/net/tap/Makefile
> @@ -0,0 +1,57 @@
> +# BSD LICENSE
> +#
> +# Copyright(c) 2016 Intel Corporation. All rights reserved.
> +#
> +# Redistribution and use in source and binary forms, with or without
> +# modification, are permitted provided that the following conditions
> +# are met:
> +#
> +# * Redistributions of source code must retain the above copyright
> +# notice, this list of conditions and the following disclaimer.
> +# * Redistributions in binary form must reproduce the above copyright
> +# notice, this list of conditions and the following disclaimer in
> +# the documentation and/or other materials provided with the
> +# distribution.
> +# * Neither the name of Intel Corporation nor the names of its
> +# contributors may be used to endorse or promote products derived
> +# from this software without specific prior written permission.
> +#
> +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +include $(RTE_SDK)/mk/rte.vars.mk
> +
> +#
> +# library name
> +#
> +LIB = librte_pmd_tap.a
> +
> +EXPORT_MAP := rte_pmd_tap_version.map
> +
> +LIBABIVER := 1
> +
> +CFLAGS += -O3
> +CFLAGS += $(WERROR_FLAGS)
> +
> +#
> +# all source are stored in SRCS-y
> +#
> +SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c
> +
> +# this lib depends upon:
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mbuf
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_mempool
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_ether
> +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_kvargs
> +
> +include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
> new file mode 100644
> index 0000000..976f2d9
> --- /dev/null
> +++ b/drivers/net/tap/rte_eth_tap.c
> @@ -0,0 +1,765 @@
> +/*-
> + * BSD LICENSE
> + *
> + * Copyright(c) 2016 Intel Corporation. All rights reserved.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in
> + * the documentation and/or other materials provided with the
> + * distribution.
> + * * Neither the name of Intel Corporation nor the names of its
> + * contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <rte_mbuf.h>
> +#include <rte_ethdev.h>
> +#include <rte_malloc.h>
> +#include <rte_vdev.h>
> +#include <rte_kvargs.h>
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/socket.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <unistd.h>
> +#include <poll.h>
> +#include <arpa/inet.h>
> +#include <linux/if.h>
> +#include <linux/if_tun.h>
> +#include <linux/if_ether.h>
> +#include <fcntl.h>
> +
> +/* Linux based path to the TUN device */
> +#define TUN_TAP_DEV_PATH "/dev/net/tun"
> +#define DEFAULT_TAP_NAME "dtap"
> +
> +#define ETH_TAP_IFACE_ARG "iface"
> +#define ETH_TAP_SPEED_ARG "speed"
> +
> +#define RTE_PMD_TAP_MAX_QUEUES 16
> +
> +static struct rte_vdev_driver pmd_tap_drv;
> +
> +static const char *valid_arguments[] = {
> + ETH_TAP_IFACE_ARG,
> + ETH_TAP_SPEED_ARG,
> + NULL
> +};
> +
> +static int tap_unit;
> +
> +static struct rte_eth_link pmd_link = {
> + .link_speed = ETH_SPEED_NUM_10G,
> + .link_duplex = ETH_LINK_FULL_DUPLEX,
> + .link_status = ETH_LINK_DOWN,
> + .link_autoneg = ETH_LINK_SPEED_AUTONEG
> +};
> +
> +struct pkt_stats {
> + uint64_t opackets; /* Number of output packets */
> + uint64_t ipackets; /* Number of input packets */
> + uint64_t obytes; /* Number of bytes on output */
> + uint64_t ibytes; /* Number of bytes on input */
> + uint64_t errs; /* Number of error packets */
> +};
> +
> +struct rx_queue {
> + struct rte_mempool *mp; /* Mempool for RX packets */
> + uint16_t in_port; /* Port ID */
> + int fd;
> +
> + struct pkt_stats stats; /* Stats for this RX queue */
> +};
> +
> +struct tx_queue {
> + int fd;
> + struct pkt_stats stats; /* Stats for this TX queue */
> +};
> +
> +struct pmd_internals {
> + char name[RTE_ETH_NAME_MAX_LEN]; /* Internal Tap device name */
> + uint16_t nb_queues; /* Number of queues supported */
> + struct ether_addr eth_addr; /* Mac address of the device port */
> +
> + int if_index; /* IF_INDEX for the port */
> + int fds[RTE_PMD_TAP_MAX_QUEUES]; /* List of all file descriptors */
> +
> + struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES]; /* List of RX queues */
> + struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX queues */
> +};
> +
> +/* Tun/Tap allocation routine
> + *
> + * name is the number of the interface to use, unless NULL to take the host
> + * supplied name.
> + */
> +static int
> +tun_alloc(char *name)
> +{
> + struct ifreq ifr;
> + unsigned int features;
> + int fd;
> +
> + memset(&ifr, 0, sizeof(struct ifreq));
> +
> + ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
> + if (name && name[0])
> + strncpy(ifr.ifr_name, name, IFNAMSIZ);
> +
> + fd = open(TUN_TAP_DEV_PATH, O_RDWR);
> + if (fd < 0) {
> + RTE_LOG(ERR, PMD, "Unable to create TAP interface");
> + goto error;
> + }
> +
> + /* Grab the TUN features to verify we can work */
> + if (ioctl(fd, TUNGETFEATURES, &features) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to get TUN/TAP features\n");
> + goto error;
> + }
> + RTE_LOG(DEBUG, PMD, "TUN/TAP Features %08x\n", features);
> +
> + if (!(features & IFF_MULTI_QUEUE) && (RTE_PMD_TAP_MAX_QUEUES > 1)) {
> + RTE_LOG(DEBUG, PMD, "TUN/TAP device only one queue\n");
> + goto error;
> + } else if ((features & IFF_ONE_QUEUE) &&
> + (RTE_PMD_TAP_MAX_QUEUES == 1)) {
> + ifr.ifr_flags |= IFF_ONE_QUEUE;
> + RTE_LOG(DEBUG, PMD, "Single queue only support\n");
> + } else {
> + ifr.ifr_flags |= IFF_MULTI_QUEUE;
> + RTE_LOG(DEBUG, PMD, "Multi-queue support for %d queues\n",
> + RTE_PMD_TAP_MAX_QUEUES);
> + }
> +
> + /* Set the TUN/TAP configuration and get the name if needed */
> + if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to set TUNSETIFF for %s\n",
> + ifr.ifr_name);
> + perror("TUNSETIFF");
> + goto error;
> + }
> +
> + /* Always set the file descriptor to non-blocking */
> + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
> + RTE_LOG(ERR, PMD, "Unable to set to nonblocking\n");
> + perror("F_SETFL, NONBLOCK");
> + goto error;
> + }
> +
> + /* If the name is different that new name as default */
> + if (name && strcmp(name, ifr.ifr_name))
> + snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", ifr.ifr_name);
> +
> + return fd;
> +
> +error:
> + if (fd > 0)
> + close(fd);
> + return -1;
> +}
> +
> +/* Callback to handle the rx burst of packets to the correct interface and
> + * file descriptor(s) in a multi-queue setup.
> + */
> +static uint16_t
> +pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> +{
> + int len;
> + struct rte_mbuf *mbuf;
> + struct rx_queue *rxq = queue;
> + uint16_t num_rx;
> + unsigned long num_rx_bytes = 0;
> +
> + for (num_rx = 0; num_rx < nb_pkts; ) {
> + /* allocate the next mbuf */
> + mbuf = rte_pktmbuf_alloc(rxq->mp);
> + if (unlikely(!mbuf)) {
> + RTE_LOG(WARNING, PMD, "Unable to allocate mbuf\n");
> + break;
> + }
> +
> + len = read(rxq->fd, rte_pktmbuf_mtod(mbuf, char *),
> + rte_pktmbuf_tailroom(mbuf));
> + if (len <= 0) {
> + rte_pktmbuf_free(mbuf);
> + break;
> + }
> +
> + mbuf->data_len = len;
> + mbuf->pkt_len = len;
> + mbuf->port = rxq->in_port;
> +
> + /* account for the receive frame */
> + bufs[num_rx++] = mbuf;
> + num_rx_bytes += mbuf->pkt_len;
> + }
> + rxq->stats.ipackets += num_rx;
> + rxq->stats.ibytes += num_rx_bytes;
> +
> + return num_rx;
> +}
> +
> +/* Callback to handle sending packets from the tap interface
> + */
> +static uint16_t
> +pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
> +{
> + struct rte_mbuf *mbuf;
> + struct tx_queue *txq = queue;
> + struct pollfd pfd;
> + uint16_t num_tx = 0;
> + unsigned long num_tx_bytes = 0;
> + int i, n;
> +
> + if (unlikely(nb_pkts == 0))
> + return 0;
> +
> + pfd.events = POLLOUT;
> + pfd.fd = txq->fd;
> + for (i = 0; i < nb_pkts; i++) {
> + n = poll(&pfd, 1, 0);
> +
> + if (n <= 0)
> + break;
> +
> + if (pfd.revents & POLLOUT) {
> + /* copy the tx frame data */
> + mbuf = bufs[num_tx];
> + n = write(pfd.fd, rte_pktmbuf_mtod(mbuf, void*),
> + rte_pktmbuf_pkt_len(mbuf));
> + if (n <= 0)
> + break;
> +
> + num_tx++;
> + num_tx_bytes += mbuf->pkt_len;
> + rte_pktmbuf_free(mbuf);
> + }
> + }
> +
> + txq->stats.opackets += num_tx;
> + txq->stats.errs += nb_pkts - num_tx;
> + txq->stats.obytes += num_tx_bytes;
> +
> + return num_tx;
> +}
> +
> +static int
> +tap_dev_start(struct rte_eth_dev *dev)
> +{
> + /* Force the Link up */
> + dev->data->dev_link.link_status = ETH_LINK_UP;
> +
> + return 0;
> +}
> +
> +/* This function gets called when the current port gets stopped.
> + */
> +static void
> +tap_dev_stop(struct rte_eth_dev *dev)
> +{
> + int i;
> + struct pmd_internals *internals = dev->data->dev_private;
> +
> + for (i = 0; i < internals->nb_queues; i++)
> + if (internals->fds[i] != -1)
> + close(internals->fds[i]);
> +
> + dev->data->dev_link.link_status = ETH_LINK_DOWN;
> +}
> +
> +static int
> +tap_dev_configure(struct rte_eth_dev *dev __rte_unused)
> +{
> + return 0;
> +}
> +
> +static void
> +tap_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> +
> + dev_info->if_index = internals->if_index;
> + dev_info->max_mac_addrs = 1;
> + dev_info->max_rx_pktlen = (uint32_t)ETHER_MAX_VLAN_FRAME_LEN;
> + dev_info->max_rx_queues = internals->nb_queues;
> + dev_info->max_tx_queues = internals->nb_queues;
> + dev_info->min_rx_bufsize = 0;
> + dev_info->pci_dev = NULL;
> +}
> +
> +static void
> +tap_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *tap_stats)
> +{
> + unsigned int i, imax;
> + unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0;
> + unsigned long rx_bytes_total = 0, tx_bytes_total = 0;
> + const struct pmd_internals *pmd = dev->data->dev_private;
> +
> + imax = (pmd->nb_queues < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
> + pmd->nb_queues : RTE_ETHDEV_QUEUE_STAT_CNTRS;
> +
> + for (i = 0; i < imax; i++) {
> + tap_stats->q_ipackets[i] = pmd->rxq[i].stats.ipackets;
> + tap_stats->q_ibytes[i] = pmd->rxq[i].stats.ibytes;
> + rx_total += tap_stats->q_ipackets[i];
> + rx_bytes_total += tap_stats->q_ibytes[i];
> + }
> +
> + for (i = 0; i < imax; i++) {
> + tap_stats->q_opackets[i] = pmd->txq[i].stats.opackets;
> + tap_stats->q_errors[i] = pmd->txq[i].stats.errs;
> + tap_stats->q_obytes[i] = pmd->txq[i].stats.obytes;
> + tx_total += tap_stats->q_opackets[i];
> + tx_err_total += tap_stats->q_errors[i];
> + tx_bytes_total += tap_stats->q_obytes[i];
> + }
> +
> + tap_stats->ipackets = rx_total;
> + tap_stats->ibytes = rx_bytes_total;
> + tap_stats->opackets = tx_total;
> + tap_stats->oerrors = tx_err_total;
> + tap_stats->obytes = tx_bytes_total;
> +}
> +
> +static void
> +tap_stats_reset(struct rte_eth_dev *dev)
> +{
> + int i;
> + struct pmd_internals *pmd = dev->data->dev_private;
> +
> + for (i = 0; i < pmd->nb_queues; i++) {
> + pmd->rxq[i].stats.ipackets = 0;
> + pmd->rxq[i].stats.ibytes = 0;
> + }
> +
> + for (i = 0; i < pmd->nb_queues; i++) {
> + pmd->txq[i].stats.opackets = 0;
> + pmd->txq[i].stats.errs = 0;
> + pmd->txq[i].stats.obytes = 0;
> + }
> +}
> +
> +static void
> +tap_dev_close(struct rte_eth_dev *dev __rte_unused)
> +{
> +}
> +
> +static void
> +tap_rx_queue_release(void *queue)
> +{
> + struct rx_queue *rxq = queue;
> +
> + if (rxq && (rxq->fd > 0)) {
> + close(rxq->fd);
> + rxq->fd = -1;
> + }
> +}
> +
> +static void
> +tap_tx_queue_release(void *queue)
> +{
> + struct tx_queue *txq = queue;
> +
> + if (txq && (txq->fd > 0)) {
> + close(txq->fd);
> + txq->fd = -1;
> + }
> +}
> +
> +static int
> +tap_link_update(struct rte_eth_dev *dev __rte_unused,
> + int wait_to_complete __rte_unused)
> +{
> + return 0;
> +}
> +
> +static int
> +tap_setup_queue(struct rte_eth_dev *dev,
> + struct pmd_internals *internals,
> + uint16_t qid)
> +{
> + struct rx_queue *rx = &internals->rxq[qid];
> + struct tx_queue *tx = &internals->txq[qid];
> + int fd;
> +
> + fd = rx->fd;
> + if (fd < 0) {
> + fd = tx->fd;
> + if (fd < 0) {
> + RTE_LOG(INFO, PMD, "Add queue to TAP %s for qid %d\n",
> + dev->data->name, qid);
> + fd = tun_alloc(dev->data->name);
> + if (fd < 0) {
> + RTE_LOG(ERR, PMD, "tun_alloc(%s) failed\n",
> + dev->data->name);
> + return -1;
> + }
> + }
> + }
> + dev->data->rx_queues[qid] = rx;
> + dev->data->tx_queues[qid] = tx;
> +
> + rx->fd = fd;
> + tx->fd = fd;
> +
> + return fd;
> +}
> +
> +static int
> +tap_rx_queue_setup(struct rte_eth_dev *dev,
> + uint16_t rx_queue_id,
> + uint16_t nb_rx_desc __rte_unused,
> + unsigned int socket_id __rte_unused,
> + const struct rte_eth_rxconf *rx_conf __rte_unused,
> + struct rte_mempool *mp)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + uint16_t buf_size;
> + int fd;
> +
> + if ((rx_queue_id >= internals->nb_queues) || !mp) {
> + RTE_LOG(ERR, PMD, "nb_queues %d mp %p\n",
> + internals->nb_queues, mp);
> + return -1;
> + }
> +
> + internals->rxq[rx_queue_id].mp = mp;
> + internals->rxq[rx_queue_id].in_port = dev->data->port_id;
> +
> + /* Now get the space available for data in the mbuf */
> + buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
> + RTE_PKTMBUF_HEADROOM);
> +
> + if (buf_size < ETH_FRAME_LEN) {
> + RTE_LOG(ERR, PMD,
> + "%s: %d bytes will not fit in mbuf (%d bytes)\n",
> + dev->data->name, ETH_FRAME_LEN, buf_size);
> + return -ENOMEM;
> + }
> +
> + fd = tap_setup_queue(dev, internals, rx_queue_id);
> + if (fd == -1)
> + return -1;
> +
> + internals->fds[rx_queue_id] = fd;
> + RTE_LOG(INFO, PMD, "RX TAP device name %s, qid %d on fd %d\n",
> + dev->data->name, rx_queue_id, internals->rxq[rx_queue_id].fd);
> +
> + return 0;
> +}
> +
> +static int
> +tap_tx_queue_setup(struct rte_eth_dev *dev,
> + uint16_t tx_queue_id,
> + uint16_t nb_tx_desc __rte_unused,
> + unsigned int socket_id __rte_unused,
> + const struct rte_eth_txconf *tx_conf __rte_unused)
> +{
> + struct pmd_internals *internals = dev->data->dev_private;
> + int ret;
> +
> + if (tx_queue_id >= internals->nb_queues)
> + return -1;
> +
> + ret = tap_setup_queue(dev, internals, tx_queue_id);
> + if (ret == -1)
> + return -1;
> +
> + RTE_LOG(INFO, PMD, "TX TAP device name %s, qid %d on fd %d\n",
> + dev->data->name, tx_queue_id, internals->txq[tx_queue_id].fd);
> +
> + return 0;
> +}
> +
> +static const struct eth_dev_ops ops = {
> + .dev_start = tap_dev_start,
> + .dev_stop = tap_dev_stop,
> + .dev_close = tap_dev_close,
> + .dev_configure = tap_dev_configure,
> + .dev_infos_get = tap_dev_info,
> + .rx_queue_setup = tap_rx_queue_setup,
> + .tx_queue_setup = tap_tx_queue_setup,
> + .rx_queue_release = tap_rx_queue_release,
> + .tx_queue_release = tap_tx_queue_release,
> + .link_update = tap_link_update,
> + .stats_get = tap_stats_get,
> + .stats_reset = tap_stats_reset,
> +};
> +
> +static int
> +pmd_mac_address(int fd, struct rte_eth_dev *dev, struct ether_addr *addr)
> +{
> + struct ifreq ifr;
> +
> + if ((fd <= 0) || !dev || !addr)
> + return -1;
> +
> + memset(&ifr, 0, sizeof(ifr));
> +
> + if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
> + RTE_LOG(ERR, PMD, "ioctl failed (SIOCGIFHWADDR) (%s)\n",
> + ifr.ifr_name);
> + return -1;
> + }
> +
> + /* Set the host based MAC address to this special MAC format */
> + ifr.ifr_hwaddr.sa_data[0] = 'T';
> + ifr.ifr_hwaddr.sa_data[1] = 'a';
> + ifr.ifr_hwaddr.sa_data[2] = 'p';
> + ifr.ifr_hwaddr.sa_data[3] = '-';
> + ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
> + ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
> + if (ioctl(fd, SIOCSIFHWADDR, &ifr) == -1) {
> + RTE_LOG(ERR, PMD, "%s: ioctl failed (SIOCSIFHWADDR) (%s)\n",
> + dev->data->name, ifr.ifr_name);
> + return -1;
> + }
> +
> + /* Set the local application MAC address, needs to be different then
> + * the host based MAC address.
> + */
> + ifr.ifr_hwaddr.sa_data[0] = 'd';
> + ifr.ifr_hwaddr.sa_data[1] = 'n';
> + ifr.ifr_hwaddr.sa_data[2] = 'e';
> + ifr.ifr_hwaddr.sa_data[3] = 't';
> + ifr.ifr_hwaddr.sa_data[4] = dev->data->port_id;
> + ifr.ifr_hwaddr.sa_data[5] = dev->data->numa_node;
> + rte_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
> +
> + return 0;
> +}
> +
> +static int
> +eth_dev_tap_create(const char *name, char *tap_name)
> +{
> + int numa_node = rte_socket_id();
> + struct rte_eth_dev *dev = NULL;
> + struct pmd_internals *pmd = NULL;
> + struct rte_eth_dev_data *data = NULL;
> + int i, fd = -1;
> +
> + RTE_LOG(INFO, PMD,
> + "%s: Create TAP Ethernet device with %d queues on numa %u\n",
> + name, RTE_PMD_TAP_MAX_QUEUES, rte_socket_id());
> +
> + data = rte_zmalloc_socket(tap_name, sizeof(*data), 0, numa_node);
> + if (!data) {
> + RTE_LOG(INFO, PMD, "Failed to allocate data\n");
> + goto error_exit;
> + }
> +
> + pmd = rte_zmalloc_socket(tap_name, sizeof(*pmd), 0, numa_node);
> + if (!pmd) {
> + RTE_LOG(INFO, PMD, "Unable to allocate internal struct\n");
> + goto error_exit;
> + }
> +
> + /* Use the name and not the tap_name */
> + dev = rte_eth_dev_allocate(tap_name);
> + if (!dev) {
> + RTE_LOG(INFO, PMD, "Unable to allocate device struct\n");
> + goto error_exit;
> + }
> +
> + snprintf(pmd->name, sizeof(pmd->name), "%s", tap_name);
> +
> + pmd->nb_queues = RTE_PMD_TAP_MAX_QUEUES;
> +
> + /* Setup some default values */
> + data->dev_private = pmd;
> + data->port_id = dev->data->port_id;
> + data->dev_flags = RTE_ETH_DEV_DETACHABLE;
> + data->kdrv = RTE_KDRV_NONE;
> + data->drv_name = pmd_tap_drv.driver.name;
> + data->numa_node = numa_node;
> +
> + data->dev_link = pmd_link;
> + data->mac_addrs = &pmd->eth_addr;
> + data->nb_rx_queues = pmd->nb_queues;
> + data->nb_tx_queues = pmd->nb_queues;
> +
> + dev->data = data;
> + dev->dev_ops = &ops;
> + dev->driver = NULL;
> + dev->rx_pkt_burst = pmd_rx_burst;
> + dev->tx_pkt_burst = pmd_tx_burst;
> + snprintf(dev->data->name, sizeof(dev->data->name), "%s", name);
> +
> + /* Create the first Tap device */
> + fd = tun_alloc(tap_name);
> + if (fd < 0) {
> + RTE_LOG(INFO, PMD, "tun_alloc() failed\n");
> + goto error_exit;
> + }
> +
> + /* Presetup the fds to -1 as being not working */
> + for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
> + pmd->fds[i] = -1;
> + pmd->rxq[i].fd = -1;
> + pmd->txq[i].fd = -1;
> + }
> +
> + /* Take the TUN/TAP fd and place in the first location */
> + pmd->rxq[0].fd = fd;
> + pmd->txq[0].fd = fd;
> + pmd->fds[0] = fd;
> +
> + if (pmd_mac_address(fd, dev, &pmd->eth_addr) < 0) {
> + RTE_LOG(INFO, PMD, "Unable to get MAC address\n");
> + goto error_exit;
> + }
> +
> + return 0;
> +
> +error_exit:
> + RTE_PMD_DEBUG_TRACE("Unable to initialize %s\n", name);
> +
> + rte_free(data);
> + rte_free(pmd);
> +
> + rte_eth_dev_release_port(dev);
> +
> + return -EINVAL;
> +}
> +
> +static int
> +set_interface_name(const char *key __rte_unused,
> + const char *value,
> + void *extra_args)
> +{
> + char *name = (char *)extra_args;
> +
> + if (value)
> + snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s", value);
> + else
> + snprintf(name, RTE_ETH_NAME_MAX_LEN - 1, "%s%d",
> + DEFAULT_TAP_NAME, (tap_unit - 1));
> +
> + return 0;
> +}
> +
> +static int
> +set_interface_speed(const char *key __rte_unused,
> + const char *value,
> + void *extra_args)
> +{
> + *(int *)extra_args = (value) ? atoi(value) : ETH_SPEED_NUM_10G;
> +
> + return 0;
> +}
> +
> +/* Open a TAP interface device.
> + */
> +static int
> +rte_pmd_tap_probe(const char *name, const char *params)
> +{
> + int ret;
> + struct rte_kvargs *kvlist = NULL;
> + int speed;
> + char tap_name[RTE_ETH_NAME_MAX_LEN];
> +
> + speed = ETH_SPEED_NUM_10G;
> + snprintf(tap_name, sizeof(tap_name), "%s%d",
> + DEFAULT_TAP_NAME, tap_unit++);
> +
> + RTE_LOG(INFO, PMD, "Initializing pmd_tap for %s as %s\n",
> + name, tap_name);
> +
> + if (params && (params[0] != '\0')) {
> + RTE_LOG(INFO, PMD, "paramaters (%s)\n", params);
> +
> + kvlist = rte_kvargs_parse(params, valid_arguments);
> + if (kvlist) {
> + if (rte_kvargs_count(kvlist, ETH_TAP_SPEED_ARG) == 1) {
> + ret = rte_kvargs_process(kvlist,
> + ETH_TAP_SPEED_ARG,
> + &set_interface_speed,
> + &speed);
> + if (ret == -1)
> + goto leave;
> + }
> +
> + if (rte_kvargs_count(kvlist, ETH_TAP_IFACE_ARG) == 1) {
> + ret = rte_kvargs_process(kvlist,
> + ETH_TAP_IFACE_ARG,
> + &set_interface_name,
> + tap_name);
> + if (ret == -1)
> + goto leave;
> + }
> + }
> + }
> + pmd_link.link_speed = speed;
> +
> + ret = eth_dev_tap_create(name, tap_name);
> +
> +leave:
> + if (ret == -1) {
> + RTE_LOG(INFO, PMD, "Failed to create pmd for %s as %s\n",
> + name, tap_name);
> + tap_unit--; /* Restore the unit number */
> + }
> + rte_kvargs_free(kvlist);
> +
> + return ret;
> +}
> +
> +/* detach a TAP device.
> + */
> +static int
> +rte_pmd_tap_remove(const char *name)
> +{
> + struct rte_eth_dev *eth_dev = NULL;
> + struct pmd_internals *internals;
> + int i;
> +
> + RTE_LOG(INFO, PMD, "Closing TUN/TAP Ethernet device on numa %u\n",
> + rte_socket_id());
> +
> + /* find the ethdev entry */
> + eth_dev = rte_eth_dev_allocated(name);
> + if (!eth_dev)
> + return 0;
> +
> + internals = eth_dev->data->dev_private;
> + for (i = 0; i < internals->nb_queues; i++)
> + if (internals->fds[i] != -1)
> + close(internals->fds[i]);
> +
> + rte_free(eth_dev->data->dev_private);
> + rte_free(eth_dev->data);
> +
> + rte_eth_dev_release_port(eth_dev);
> +
> + return 0;
> +}
> +
> +static struct rte_vdev_driver pmd_tap_drv = {
> + .probe = rte_pmd_tap_probe,
> + .remove = rte_pmd_tap_remove,
> +};
> +RTE_PMD_REGISTER_VDEV(net_tap, pmd_tap_drv);
> +RTE_PMD_REGISTER_ALIAS(net_tap, eth_tap);
> +RTE_PMD_REGISTER_PARAM_STRING(net_tap, "iface=<string>,speed=N");
> diff --git a/drivers/net/tap/rte_pmd_tap_version.map b/drivers/net/tap/rte_pmd_tap_version.map
> new file mode 100644
> index 0000000..31eca32
> --- /dev/null
> +++ b/drivers/net/tap/rte_pmd_tap_version.map
> @@ -0,0 +1,4 @@
> +DPDK_17.02 {
> +
> + local: *;
> +};
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index f75f0e2..02c32ae 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -124,6 +124,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += -lrte_pmd_pcap -lpcap
> _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += -lrte_pmd_qede
> _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING) += -lrte_pmd_ring
> _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += -lrte_pmd_szedata2 -lsze2
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += -lrte_pmd_tap
> _LDLIBS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += -lrte_pmd_thunderx_nicvf -lm
> _LDLIBS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += -lrte_pmd_virtio
> ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y)
> --
> 2.8.0.GIT
>
>
Regards,
Keith
^ permalink raw reply
* Re: [PATCH 7/7] net/qede: restrict maximum queues for PF/VF
From: Ferruh Yigit @ 2016-12-12 20:10 UTC (permalink / raw)
To: Harish Patil, dev@dpdk.org; +Cc: Dept-Eng DPDK Dev
In-Reply-To: <D47438FD.C04E6%Harish.Patil@cavium.com>
On 12/12/2016 7:29 PM, Harish Patil wrote:
>
>> On 12/3/2016 2:43 AM, Harish Patil wrote:
>>> Fix to adverstise max_rx_queues by taking into account the number
>>
>> s/adverstise/advertise
>
> Will correct that, thanks.
>
>>
>>> of PF connections instead of returning max_queues supported by the
>>> HW.
>>
>> Can you please describe what is the effect, what happens if this is not
>> fixed, and driver keeps reporting max_queues supported by the HW?
>
> We have tested up to 32 Rx/Tx queues across different qede devices, so I
> would like to advertise only those many.
> Hope that is okay.
That is OK, can you please add this information to the commit log,
otherwise it is not possible to know the reasoning of the change just
with code.
Thanks.
>
>>
>>>
>>> Fixes: 2ea6f76a ("qede: add core driver")
>>>
>>> Signed-off-by: Harish Patil <harish.patil@qlogic.com>
>>> ---
>> <...>
>>
>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox