DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 22/32] app/testpmd: use multicast promiscuous mode on i40e
From: Lu, Wenzhuo @ 2016-12-13  1:45 UTC (permalink / raw)
  To: Yigit, Ferruh, dev@dpdk.org
In-Reply-To: <d5e65a79-9400-a110-ab50-6ab05be4f440@intel.com>

Hi Ferruh,


> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, December 7, 2016 11:02 PM
> To: Lu, Wenzhuo; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v2 22/32] app/testpmd: use multicast
> promiscuous mode on i40e
> 
> On 12/7/2016 3:32 AM, Wenzhuo Lu wrote:
> > Add testpmd CLI to set VF multicast promiscuous mode on i40e.
> >
> > Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
> > ---
> >  app/test-pmd/cmdline.c                      | 86 +++++++++++++++++++++++++++++
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  8 +++
> >  2 files changed, 94 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > d39712e..7e7a016 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -407,6 +407,9 @@ static void cmd_help_long_parsed(void
> > *parsed_result,  #ifdef RTE_LIBRTE_I40E_PMD
> >  			"set vf unicast-promisc (port_id) (vf_id) (on|off)\n"
> >  			"    Set unicast promiscuous mode for a VF from the
> PF.\n\n"
> > +
> > +			"set vf multicast-promisc (port_id) (vf_id) (on|off)\n"
> > +			"    Set multicast promiscuous mode for a VF from the
> PF.\n\n"
> 
> Why not "allmulti" instead of multicast-promisc?
> 
> Also same comments as previous patch for help_str and documentation.
Sorry for the late. You're right, I should not change the word. Will send a V3.

> 
> <...>

^ permalink raw reply

* [-- 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),
 					  &reg_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 = &eth_addr;
> +
> +	eth_dev->data = data;
> +	eth_dev->dev_ops = &eth_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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox