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