[dpdk-dev] i40e: problem with rx packet drops not accounted in statistics
Hi Martin Yes, we have a developer working on it now, and hopefully he will have something soon later on this fix. But what do you mean the performance problem? Did you mean the performance number is not good as expected, or else? Regards, Helin > -Original Message- > From: Martin Weiser [mailto:martin.weiser at allegro-packets.com] > Sent: Wednesday, October 21, 2015 4:44 PM > To: Zhang, Helin > Cc: dev at dpdk.org > Subject: Re: i40e: problem with rx packet drops not accounted in statistics > > Hi Helin, > > any news on this issue? By the way this is not just a problem with statistics > for us > but also a performance problem since these packet discards start appearing at > a > relatively low bandwidth (~5GBit/s and ~1.5Mpps). > > Best regards, > Martin > > On 10.09.15 03:09, Zhang, Helin wrote: > > Hi Martin > > > > Yes, the statistics issue has been reported several times recently. > > We will check the issue and try to fix it or get a workaround soon. Thank > > you > very much! > > > > Regards, > > Helin > > > >> -Original Message- > >> From: Martin Weiser [mailto:martin.weiser at allegro-packets.com] > >> Sent: Wednesday, September 9, 2015 7:58 PM > >> To: Zhang, Helin > >> Cc: dev at dpdk.org > >> Subject: i40e: problem with rx packet drops not accounted in > >> statistics > >> > >> Hi Helin, > >> > >> in one of our test setups involving i40e adapters we are experiencing > >> packet drops which are not reflected in the interfaces statistics. > >> The call to rte_eth_stats_get suggests that all packets were properly > >> received but the total number of packets received through > >> rte_eth_rx_burst is less than the ipackets counter. > >> When for example running the l2fwd application (l2fwd -c 0xfe -n 4 -- > >> -p > >> 0x3) and having driver debug messages enabled the following output is > >> generated for the interface in question: > >> > >> ... > >> PMD: i40e_update_vsi_stats(): * VSI[6] stats start > >> *** > >> PMD: i40e_update_vsi_stats(): rx_bytes:24262434 > >> PMD: i40e_update_vsi_stats(): rx_unicast: 16779 > >> PMD: i40e_update_vsi_stats(): rx_multicast:0 > >> PMD: i40e_update_vsi_stats(): rx_broadcast:0 > >> PMD: i40e_update_vsi_stats(): rx_discards: 1192557 > >> PMD: i40e_update_vsi_stats(): rx_unknown_protocol: 0 > >> PMD: i40e_update_vsi_stats(): tx_bytes:0 > >> PMD: i40e_update_vsi_stats(): tx_unicast: 0 > >> PMD: i40e_update_vsi_stats(): tx_multicast:0 > >> PMD: i40e_update_vsi_stats(): tx_broadcast:0 > >> PMD: i40e_update_vsi_stats(): tx_discards: 0 > >> PMD: i40e_update_vsi_stats(): tx_errors: 0 > >> PMD: i40e_update_vsi_stats(): * VSI[6] stats end > >> *** > >> PMD: i40e_dev_stats_get(): * PF stats start > >> *** > >> PMD: i40e_dev_stats_get(): rx_bytes:24262434 > >> PMD: i40e_dev_stats_get(): rx_unicast: 16779 > >> PMD: i40e_dev_stats_get(): rx_multicast:0 > >> PMD: i40e_dev_stats_get(): rx_broadcast:0 > >> PMD: i40e_dev_stats_get(): rx_discards: 0 > >> PMD: i40e_dev_stats_get(): rx_unknown_protocol: 16779 > >> PMD: i40e_dev_stats_get(): tx_bytes:0 > >> PMD: i40e_dev_stats_get(): tx_unicast: 0 > >> PMD: i40e_dev_stats_get(): tx_multicast:0 > >> PMD: i40e_dev_stats_get(): tx_broadcast:0 > >> PMD: i40e_dev_stats_get(): tx_discards: 0 > >> PMD: i40e_dev_stats_get(): tx_errors: 0 > >> PMD: i40e_dev_stats_get(): tx_dropped_link_down: 0 > >> PMD: i40e_dev_stats_get(): crc_errors: 0 > >> PMD: i40e_dev_stats_get(): illegal_bytes:0 > >> PMD: i40e_dev_stats_get(): error_bytes: 0 > >> PMD: i40e_dev_stats_get(): mac_local_faults: 1 > >> PMD: i40e_dev_stats_get(): mac_remote_faults:1 > >> PMD: i40e_dev_stats_get(): rx_length_errors: 0 > >> PMD: i40e_dev_stats_get(): link_xon_rx: 0 > >> PMD: i40e_dev_stats_get(): link_xoff_rx: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[0]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[0]: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[1]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[1]: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[2]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[2]: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[3]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[3]: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[4]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[4]: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[5]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[5]: 0 > >> PMD: i40e_dev_stats_get(): priority_xon_rx[6]: 0 > >> PMD: i40e_dev_stats_get(): priority_xoff_rx[6]: 0 > >> PMD: i40e_dev_stats_get(
[dpdk-dev] [PATCH 5/6] doc: Update BNX2X PMD documentation
> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > Sent: Tuesday, October 20, 2015 9:20 AM > > This patch can be avoided by updating the documentation with each code > change atomically. Agreed, will take care in next submission. This message and any attached documents contain information from the sending company or its parent company(s), subsidiaries, divisions or branch offices that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.
[dpdk-dev] [PATCH 4/6] config: Enable BNX2X driver build by default
> From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > Sent: Tuesday, October 20, 2015 9:18 AM > > 2015-10-08 09:54, Rasesh Mody: > > From: Harish Patil > > > > Signed-off-by: Harish Patil > > Signed-off-by: Rasesh Mody > > You cannot enable bnx2x without gracefully handle miss of zlib header. Ok, will resubmit this. Thanks! Rasesh This message and any attached documents contain information from the sending company or its parent company(s), subsidiaries, divisions or branch offices that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.
[dpdk-dev] [PATCH v2 6/6] ixgbe: implementation for fdir new modes' config
Hi Konstantin, > -Original Message- > From: Ananyev, Konstantin > Sent: Wednesday, October 21, 2015 6:19 PM > To: Lu, Wenzhuo; dev at dpdk.org > Subject: RE: [dpdk-dev] [PATCH v2 6/6] ixgbe: implementation for fdir new > modes' config > > > > > -Original Message- > > From: Lu, Wenzhuo > > Sent: Wednesday, October 21, 2015 2:48 AM > > To: Ananyev, Konstantin; dev at dpdk.org > > Subject: RE: [dpdk-dev] [PATCH v2 6/6] ixgbe: implementation for fdir > > new modes' config > > > > Hi Konstantin, > > > > > -Original Message- > > > From: Ananyev, Konstantin > > > Sent: Tuesday, October 20, 2015 9:56 PM > > > To: Lu, Wenzhuo; dev at dpdk.org > > > Subject: RE: [dpdk-dev] [PATCH v2 6/6] ixgbe: implementation for > > > fdir new modes' config > > > > > > Hi Wenzhuo, > > > Few questions/comments from me, see below. > > > Thanks > > > Konstantin > > > > > > > -Original Message- > > > > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Wenzhuo Lu > > > > Sent: Tuesday, September 29, 2015 6:31 AM > > > > To: dev at dpdk.org > > > > Subject: [dpdk-dev] [PATCH v2 6/6] ixgbe: implementation for fdir > > > > new modes' config > > > > > > > > Implement the new CLIs for fdir mac vlan and tunnel modes, > > > > including flow_director_filter and flow_director_mask. Set the mask of > fdir. > > > > Add, delete or update the entities of filter. > > > > > > > > Signed-off-by: Wenzhuo Lu > > > > --- > > > > drivers/net/ixgbe/ixgbe_ethdev.h | 3 + > > > > drivers/net/ixgbe/ixgbe_fdir.c | 241 > > > --- > > > > 2 files changed, 202 insertions(+), 42 deletions(-) > > > > > > > > diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h > > > > b/drivers/net/ixgbe/ixgbe_ethdev.h > > > > index c3d4f4f..9cc45a0 100644 > > > > --- a/drivers/net/ixgbe/ixgbe_ethdev.h > > > > +++ b/drivers/net/ixgbe/ixgbe_ethdev.h > > > > @@ -133,6 +133,9 @@ struct ixgbe_hw_fdir_mask { > > > > uint16_t src_port_mask; > > > > uint16_t dst_port_mask; > > > > uint16_t flex_bytes_mask; > > > > + uint8_t mac_addr_mask; > > > > + uint32_t tunnel_id_mask; > > > > + uint8_t tunnel_type_mask; > > > > }; > > > > > > > > struct ixgbe_hw_fdir_info { > > > > diff --git a/drivers/net/ixgbe/ixgbe_fdir.c > > > > b/drivers/net/ixgbe/ixgbe_fdir.c index 5c8b833..87e7081 100644 > > > > --- a/drivers/net/ixgbe/ixgbe_fdir.c > > > > +++ b/drivers/net/ixgbe/ixgbe_fdir.c > > > > @@ -105,6 +105,8 @@ > > > > rte_memcpy((ipaddr), ipv6_addr, sizeof(ipv6_addr));\ } while > > > > (0) > > > > > > > > +#define DEFAULT_VXLAN_PORT 4789 > > > > + > > > > static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t > > > > fdirhash); static int fdir_set_input_mask_82599(struct rte_eth_dev > *dev, > > > > const struct rte_eth_fdir_masks *input_mask); @@ -113,7 > > > +115,8 @@ > > > > static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, > > > > static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t > > > > fdirctrl); static int ixgbe_fdir_filter_to_atr_input( > > > > const struct rte_eth_fdir_filter *fdir_filter, > > > > - union ixgbe_atr_input *input); > > > > + union ixgbe_atr_input *input, > > > > + enum rte_fdir_mode mode); > > > > static uint32_t ixgbe_atr_compute_hash_82599(union > > > > ixgbe_atr_input > > > *atr_input, > > > > uint32_t key); > > > > static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input > > > > *input, @@ -122,7 +125,8 @@ static uint32_t > > > atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, > > > > enum rte_fdir_pballoc_type pballoc); static int > > > > fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, > > > > union ixgbe_atr_input *input, uint8_t queue, > > > > - uint32_t fdircmd, uint32_t fdirhash); > > > > + uint32_t fdircmd, uint32_t fdirhash, > > > > + enum rte_fdir_mode mode); > > > > static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw, > > > > union ixgbe_atr_input *input, u8 queue, uint32_t > > > > fdircmd, > > > > uint32_t fdirhash); > > > > @@ -243,9 +247,15 @@ configure_fdir_flags(const struct > > > > rte_fdir_conf > > > *conf, uint32_t *fdirctrl) > > > > *fdirctrl |= (IXGBE_DEFAULT_FLEXBYTES_OFFSET / sizeof(uint16_t)) > > > << > > > > IXGBE_FDIRCTRL_FLEX_SHIFT; > > > > > > > > - if (conf->mode == RTE_FDIR_MODE_PERFECT) { > > > > + if (conf->mode >= RTE_FDIR_MODE_PERFECT) { > > > > > > I think better if (conf->mode >= RTE_FDIR_MODE_PERFECT && > > > conf->mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) To make sure that > future > > > expansion of RTE_FDIR_MODE_* wouldn't break that code. > > Yes, you're right. I'll change it. > > > > > > > > > *fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH; > >
[dpdk-dev] [PATCH 1/3] fm10k: add multi-queue checking
On 2015/10/15 19:07, He, Shaopeng wrote: > Hi, Michael > >> -Original Message- >> From: Qiu, Michael >> Sent: Thursday, October 15, 2015 2:28 PM >> To: He, Shaopeng; dev at dpdk.org >> Subject: Re: [dpdk-dev] [PATCH 1/3] fm10k: add multi-queue checking >> >> On 2015/9/30 15:29, Shaopeng He wrote: >>> Add multi-queue checking in device configure process. >>> Currently, VMDQ and RSS are supported. >>> >>> Signed-off-by: Shaopeng He >>> --- >>> drivers/net/fm10k/fm10k_ethdev.c | 44 >>> >>> 1 file changed, 44 insertions(+) >>> >>> diff --git a/drivers/net/fm10k/fm10k_ethdev.c >>> b/drivers/net/fm10k/fm10k_ethdev.c >>> index a69c990..082937d 100644 >>> --- a/drivers/net/fm10k/fm10k_ethdev.c >>> +++ b/drivers/net/fm10k/fm10k_ethdev.c >>> @@ -283,12 +283,56 @@ tx_queue_disable(struct fm10k_hw *hw, >> uint16_t >>> qnum) } >>> >>> static int >>> +fm10k_check_mq_mode(struct rte_eth_dev *dev) { >>> + enum rte_eth_rx_mq_mode rx_mq_mode = dev->data- >>> dev_conf.rxmode.mq_mode; >>> + struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data- >>> dev_private); >>> + struct rte_eth_vmdq_rx_conf *vmdq_conf; >>> + uint16_t nb_rx_q = dev->data->nb_rx_queues; >>> + >>> + vmdq_conf = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; >>> + >>> + if (rx_mq_mode & ETH_MQ_RX_DCB_FLAG) { >>> + PMD_INIT_LOG(ERR, "DCB mode is not supported."); >>> + return -EINVAL; >>> + } >>> + >>> + if (!(rx_mq_mode & ETH_MQ_RX_VMDQ_FLAG)) >>> + return 0; >>> + >>> + if (hw->mac.type == fm10k_mac_vf) { >>> + PMD_INIT_LOG(ERR, "VMDQ mode is not supported in VF."); >>> + return -EINVAL; >>> + } >> I think vf check should be the first one, then we do not need check dcb and >> VMDq flag. >> >> Thanks, >> Michael > Thanks for the comments. There is a case of RSS support on VF, if vf check be > the first one, it will return fail, which is not correct. OK, you are right. Thanks, Michael > Thanks, > --Shaopeng >>> + >>> + /* Check VMDQ queue pool number */ >>> + if (vmdq_conf->nb_queue_pools > >>> + sizeof(vmdq_conf->pool_map[0].pools) * CHAR_BIT >> || >>> + vmdq_conf->nb_queue_pools > nb_rx_q) { >>> + PMD_INIT_LOG(ERR, "Too many of queue pools: %d", >>> + vmdq_conf->nb_queue_pools); >>> + return -EINVAL; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static int >>> fm10k_dev_configure(struct rte_eth_dev *dev) { >>> + int ret; >>> + >>> PMD_INIT_FUNC_TRACE(); >>> >>> if (dev->data->dev_conf.rxmode.hw_strip_crc == 0) >>> PMD_INIT_LOG(WARNING, "fm10k always strip CRC"); >>> + /* multipe queue mode checking */ >>> + ret = fm10k_check_mq_mode(dev); >>> + if (ret != 0) { >>> + PMD_DRV_LOG(ERR, "fm10k_check_mq_mode fails >> with %d.", >>> + ret); >>> + return ret; >>> + } >>> >>> return 0; >>> } >
[dpdk-dev] DPDK patch backlog
On 2015/10/16 22:25, Neil Horman wrote: > On Fri, Oct 16, 2015 at 10:45:23AM +0200, Thomas Monjalon wrote: >> 2015-10-15 14:44, Stephen Hemminger: >>> There are currently 428 patches in New state in DPDK patchwork. >>> >>> Thomas, could you start reducing that backlog? >> Yes >> >>> The simplest solution would be to merge some of the big patch series >>> from Intel for the base drivers, then reviewers can focus on the other >>> patches. >> That's why having a drivers/net subtree would be useful. >> > Agreed, a dpdk-next tree would really be the solution here. Can't agree more :) Thanks, Michael > Neil > >
[dpdk-dev] DPDK patch backlog
On 2015/10/21 17:05, Thomas Monjalon wrote: > 2015-10-21 11:48, Panu Matilainen: >> On 10/21/2015 11:25 AM, Thomas Monjalon wrote: >>> 2015-10-20 21:34, Stephen Hemminger: Patch backlog is not getting better, now at 486. How can we break this logjam? Do I need to make a new "ready for merge" tree? >>> What would mean "ready for merge"? >>> A lot of patches are acked but do not compile or doc is missing. >> Well, isn't that one quite reasonable definition of being "ready"? >> - patch must be acked >> - patch must apply and compile (when relevant) >> - is appropriately documented (commit message style and all) > Yes. > Compilation must be tested with GCC and clang, as static and shared libraries > and for 32-bit and 64-bit targets. > Documented means good commit message and doc or release notes updated. What about bug fix patches? Thanks, Michael >
[dpdk-dev] [PATCH] fix lpm bugs
hi: Fixes: 25e4f515fe63 ("fix lpm bugs") the random test of lpm , multiple delete and add ip address, it do not recover the last right ip address. eg1: add a lot of routes: rule id : 1, ip : 16.32.0.0/19, next_hop : 62, rule id : 2, ip : 16.32.28.0/22, next_hop : 97, rule id : 28, ip:16.32.0.0/21, next_hop :36 . when you delete rule id 3, then lookup 16.32.0.150, the return is 16.32.28.0/22,but not 16.32.0.0/19. this is because in delete_depth_small function, when lpm->tbl24[i].ext_entry == 0 and lpm->tbl24[i].depth > depth, it will run into the tbl8 process.then the next_hop will be doing as tbl8_gindex, and the lpm->tbl8[j] data is being wrong processed. fix: + else if (lpm->tbl24[i].ext_entry == 1) { eg2: when add ,delete and add again, it will also has problem. in delete_depth_small function, the valid_group of new struct rte_lpm_tbl8_entry is INVALID, so when process lpm->tbl8[j] = new_tbl8_entry, the valid_group is covered. and when just add a route depth > 24, and alloc a tbl8 index, then the tbl8_alloc will return it as new index, then the data is being wrong rewrite. fix:+ .valid_group = VALID, thanks.I will provide the testing program later . regards yuerxin At 2015-10-21 19:07:49, "Bruce Richardson" wrote: >On Wed, Oct 21, 2015 at 05:54:13PM +0800, mablexidana wrote: >> hi: >> We test some lpm cases and find some bugs, below is how to fix it. >> thanks :) > >Hi, > >thanks for the patch. Could you perhaps provide a description of how to >reproduce >the bug (or bugs you are fixing), so that we can reproduce them and verify the >fix. (A unit test added to the existing lpm unit tests for this would be the >best solution.) >For the patch itself, the commit message should also describe the bug, and >how the patch fixes it. It's also good to include a one-line "Fixes:" line >in the comment - generated by using the git alias "fixline" added as: > fixline = log -1 --abbrev=12 --format='Fixes: %h (\"%s\")' > >Regards, >/Bruce > >> --- >> lib/librte_lpm/rte_lpm.c | 5 +++-- >> 1 file changed, 3 insertions(+), 2 deletions(-) >> >> >> diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c >> index 163ba3c..b5199ff 100644 >> --- a/lib/librte_lpm/rte_lpm.c >> +++ b/lib/librte_lpm/rte_lpm.c >> @@ -735,7 +735,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t >> ip_masked, >> lpm->tbl24[i].depth <= depth ) { >> lpm->tbl24[i].valid = INVALID; >> } >> - else { >> + else if (lpm->tbl24[i].ext_entry == 1){ >> /* >> * If TBL24 entry is extended, then there has >> * to be a rule with depth >= 25 in the >> @@ -770,6 +770,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t >> ip_masked, >> >> >> struct rte_lpm_tbl8_entry new_tbl8_entry = { >> .valid = VALID, >> + .valid_group = VALID, >> .depth = sub_rule_depth, >> .next_hop = lpm->rules_tbl >> [sub_rule_index].next_hop, >> @@ -781,7 +782,7 @@ delete_depth_small(struct rte_lpm *lpm, uint32_t >> ip_masked, >> lpm->tbl24[i].depth <= depth ) { >> lpm->tbl24[i] = new_tbl24_entry; >> } >> - else { >> + else if (lpm->tbl24[i].ext_entry == 1) { >> /* >> * If TBL24 entry is extended, then there has >> * to be a rule with depth >= 25 in the >> -- >> 1.8.5.2 (Apple Git-48)
[dpdk-dev] [PATCH v3 6/7] virtio: simple tx routine
On 10/22/2015 10:26 AM, Jianfeng wrote: > -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Huawei Xie > Sent: Tuesday, October 20, 2015 11:30 PM > To: dev at dpdk.org > Subject: [dpdk-dev] [PATCH v3 6/7] virtio: simple tx routine > > Changes in v3: > - Remove return at the end of void function > - Remove always_inline attribute for virtio_xmit_cleanup > > bulk free of mbufs when clean used ring. > shift operation of idx could be saved if vq_free_cnt means free slots rather > than free descriptors. > > TODO: rearrange vq data structure, pack the stats var together so that we > could use one vec instruction to update all of them. > > Signed-off-by: Huawei Xie > --- > drivers/net/virtio/virtio_ethdev.h | 3 ++ > drivers/net/virtio/virtio_rxtx_simple.c | 93 > + > 2 files changed, 96 insertions(+) > > diff --git a/drivers/net/virtio/virtio_ethdev.h > b/drivers/net/virtio/virtio_ethdev.h > index d7797ab..ae2d47d 100644 > --- a/drivers/net/virtio/virtio_ethdev.h > +++ b/drivers/net/virtio/virtio_ethdev.h > @@ -111,6 +111,9 @@ uint16_t virtio_xmit_pkts(void *tx_queue, struct > rte_mbuf **tx_pkts, uint16_t virtio_recv_pkts_vec(void *rx_queue, struct > rte_mbuf **rx_pkts, > uint16_t nb_pkts); > > +uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf > **tx_pkts, > + uint16_t nb_pkts); > + > /* > * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us > * frames larger than 1514 bytes. We do not yet support software LRO diff -- > git a/drivers/net/virtio/virtio_rxtx_simple.c > b/drivers/net/virtio/virtio_rxtx_simple.c > index ef17562..a53d462 100644 > --- a/drivers/net/virtio/virtio_rxtx_simple.c > +++ b/drivers/net/virtio/virtio_rxtx_simple.c > @@ -288,6 +288,99 @@ virtio_recv_pkts_vec(void *rx_queue, struct > rte_mbuf **rx_pkts, > return nb_pkts_received; > } > > +#define VIRTIO_TX_FREE_THRESH 32 > +#define VIRTIO_TX_MAX_FREE_BUF_SZ 32 > +#define VIRTIO_TX_FREE_NR 32 > +/* TODO: vq->tx_free_cnt could mean num of free slots so we could avoid > +shift */ static inline void virtio_xmit_cleanup(struct virtqueue *vq) { > + uint16_t i, desc_idx; > + int nb_free = 0; > + struct rte_mbuf *m, *free[VIRTIO_TX_MAX_FREE_BUF_SZ]; > + > + desc_idx = (uint16_t)(vq->vq_used_cons_idx & > + ((vq->vq_nentries >> 1) - 1)); > + free[0] = (struct rte_mbuf *)vq->vq_descx[desc_idx++].cookie; > + nb_free = 1; > + > + for (i = 1; i < VIRTIO_TX_FREE_NR; i++) { > + m = (struct rte_mbuf *)vq->vq_descx[desc_idx++].cookie; > + if (likely(m->pool == free[0]->pool)) > + free[nb_free++] = m; > + else { > + rte_mempool_put_bulk(free[0]->pool, (void **)free, > + nb_free); > + free[0] = m; > + nb_free = 1; > + } > + } > + > + rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); > + vq->vq_used_cons_idx += VIRTIO_TX_FREE_NR; > + vq->vq_free_cnt += (VIRTIO_TX_FREE_NR << 1); } > + > +uint16_t > +virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, > + uint16_t nb_pkts) > +{ > + struct virtqueue *txvq = tx_queue; > + uint16_t nb_used; > + uint16_t desc_idx; > + struct vring_desc *start_dp; > + uint16_t nb_tail, nb_commit; > + int i; > + uint16_t desc_idx_max = (txvq->vq_nentries >> 1) - 1; > + > + nb_used = VIRTQUEUE_NUSED(txvq); > + rte_compiler_barrier(); > + > + nb_commit = nb_pkts = RTE_MIN((txvq->vq_free_cnt >> 1), > nb_pkts); Here if nb_commit is zero, how about return 0 immediately? > + desc_idx = (uint16_t) (txvq->vq_avail_idx & desc_idx_max); > + start_dp = txvq->vq_ring.desc; > + nb_tail = (uint16_t) (desc_idx_max + 1 - desc_idx); > + > + if (nb_used >= VIRTIO_TX_FREE_THRESH) > + virtio_xmit_cleanup(tx_queue); If this cleanup should be put before vq_free_cnt is referenced? It's because it may free some descs to vq_free_cnt. > + > + if (nb_commit >= nb_tail) { > + for (i = 0; i < nb_tail; i++) > + txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i]; > + for (i = 0; i < nb_tail; i++) { > + start_dp[desc_idx].addr = > + RTE_MBUF_DATA_DMA_ADDR(*tx_pkts); > + start_dp[desc_idx].len = (*tx_pkts)->pkt_len; > + tx_pkts++; > + desc_idx++; > + } > + nb_commit -= nb_tail; > + desc_idx = 0; > + } > + for (i = 0; i < nb_commit; i++) > + txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i]; > + for (i = 0; i < nb_commit; i++) { > + start_dp[desc_idx].addr = > RTE_MBUF_DATA_DMA_ADDR(*tx_pkts); > + start_dp[desc_idx].len = (*tx_pkts)->pkt_len; > + tx_pkts++; > +
[dpdk-dev] volunteer to be the maintainer of driver/net/intel sub-tree
Hi all, Following the discussion of DPDK user space and the maintenance of development sub-trees, I'd like to volunteer myself to be the maintainer of sub-tree driver/net/intel. It includes all the PMD of Intel NICs. And Helin can be my backup. I suggest we create a new directory to move the driver/net/e1000, driver/net/fm10k... to it. And we can also create directories for other vendors just like the kernel driver do. Additionally, as we observed, some patch sets will not only change the files in drivers/net, but also some files in lib/librte_ether, doc, app, examples... Only being drivers/net/intel maintainer cannot work for these patch sets, especially for the new features. Applying partial feature patch set is not ideal. Ideally we need a maintainer to drive the RTE_ETHER discussion. Maybe Bruce can be a top-level maintainer. So, he can help when we face this scenario. Best regards Wenzhuo Lu
[dpdk-dev] [PATCH v3 7/7] virtio: pick simple rx/tx func
On 10/22/2015 10:45 AM, Jianfeng wrote: > -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Huawei Xie > Sent: Tuesday, October 20, 2015 11:30 PM > To: dev at dpdk.org > Subject: [dpdk-dev] [PATCH v3 7/7] virtio: pick simple rx/tx func > > simple rx/tx func is enabled when user specifies single segment and no > offload support. > merge-able should be disabled to use simple rxtx. > > Signed-off-by: Huawei Xie > --- > drivers/net/virtio/virtio_rxtx.c | 12 > 1 file changed, 12 insertions(+) > > diff --git a/drivers/net/virtio/virtio_rxtx.c > b/drivers/net/virtio/virtio_rxtx.c > index 947fc46..71f8cd4 100644 > --- a/drivers/net/virtio/virtio_rxtx.c > +++ b/drivers/net/virtio/virtio_rxtx.c > @@ -62,6 +62,10 @@ > #define VIRTIO_DUMP_PACKET(m, len) do { } while (0) #endif > > + > +#define VIRTIO_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS > | \ > + ETH_TXQ_FLAGS_NOOFFLOADS) > + > static int use_simple_rxtx; > > static void > @@ -471,6 +475,14 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev > *dev, > return -EINVAL; > } > > + /* Use simple rx/tx func if single segment and no offloads */ > + if ((tx_conf->txq_flags & VIRTIO_SIMPLE_FLAGS) == > VIRTIO_SIMPLE_FLAGS) { > + PMD_INIT_LOG(INFO, "Using simple rx/tx path"); > + dev->tx_pkt_burst = virtio_xmit_pkts_simple; > + dev->rx_pkt_burst = virtio_recv_pkts_vec; Whether recv side mergeable is supported is controlled by virtio_negotiate_feature(). So "dev->rx_pkt_burst = virtio_recv_pkts_vec" should be restricted by hw->guest_features & VIRTIO_NET_F_MRG_RXBUF, right? > + use_simple_rxtx = 1; > + } > + > ret = virtio_dev_queue_setup(dev, VTNET_TQ, queue_idx, > vtpci_queue_idx, > nb_desc, socket_id, &vq); > if (ret < 0) { > -- > 1.8.1.4
[dpdk-dev] [PATCH] kni: allow per-net instances
Hi Dex Two comments inlined. Thank you very much for the really good contribution to KNI! Regards, Helin > -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Dex Chen > Sent: Thursday, July 2, 2015 6:12 PM > To: dev at dpdk.org > Subject: [dpdk-dev] [PATCH] kni: allow per-net instances > > There is a global variable 'device_in_use' which is used to make sure only one > instance is using /dev/kni device. If you were using LXC, you will find there > is only > one instance of KNI example could be run even differnt namespaces were > created. > > In order to have /dev/kni used simultaneously in different namespaces, making > all of global variables as per network namespace variables. > > With regard to single kernel thread mode, there will be one kernel thread for > each of network namespace. > > Signed-off-by: Dex Chen > --- > lib/librte_eal/linuxapp/kni/kni_misc.c | 129 > ++--- > 1 file changed, 85 insertions(+), 44 deletions(-) > > diff --git a/lib/librte_eal/linuxapp/kni/kni_misc.c > b/lib/librte_eal/linuxapp/kni/kni_misc.c > index 2e9fa89..5ba8ab8 100644 > --- a/lib/librte_eal/linuxapp/kni/kni_misc.c > +++ b/lib/librte_eal/linuxapp/kni/kni_misc.c > @@ -28,6 +28,9 @@ > #include > #include > #include > +#include > +#include > +#include > > #include > #include "kni_dev.h" > @@ -90,18 +93,48 @@ static unsigned multiple_kthread_on = 0; > > #define KNI_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */ > > -static volatile unsigned long device_in_use; /* device in use flag */ > -static struct > task_struct *kni_kthread; > +static int kni_net_id; > > -/* kni list lock */ > -static DECLARE_RWSEM(kni_list_lock); > +struct kni_net { > + volatile unsigned long device_in_use; /* device in use flag */ > + struct task_struct *kni_kthread; > + struct rw_semaphore kni_list_lock; > + struct list_head kni_list_head; > +}; > + > +static __net_init int kni_init_net(struct net *net) { > + struct kni_net *knet = net_generic(net, kni_net_id); > > -/* kni list */ > -static struct list_head kni_list_head = LIST_HEAD_INIT(kni_list_head); > + /* Clear the bit of device in use */ > + clear_bit(KNI_DEV_IN_USE_BIT_NUM, &knet->device_in_use); > + > + init_rwsem(&knet->kni_list_lock); > + INIT_LIST_HEAD(&knet->kni_list_head); > + > + return 0; > +} > + > +static __net_exit void kni_exit_net(struct net *net) { > + /* > + * Nothing to do here. > + * Assuming all cleanup jobs were done in kni_release(). > + */ > +} Agree with Stephen, kernel should handle it well. > + > +static struct pernet_operations kni_net_ops = { > + .init = kni_init_net, > + .exit = kni_exit_net, > + .id = &kni_net_id, > + .size = sizeof(struct kni_net), > +}; > > static int __init > kni_init(void) > { > + int rc; > + > KNI_PRINT(" DPDK kni module loading \n"); > > if (kni_parse_kthread_mode() < 0) { > @@ -114,8 +147,9 @@ kni_init(void) > return -EPERM; > } > > - /* Clear the bit of device in use */ > - clear_bit(KNI_DEV_IN_USE_BIT_NUM, &device_in_use); > + rc = register_pernet_subsys(&kni_net_ops); > + if (rc) > + goto out; > > /* Configure the lo mode according to the input parameter */ > kni_net_config_lo_mode(lo_mode); > @@ -123,11 +157,16 @@ kni_init(void) > KNI_PRINT(" DPDK kni module loaded \n"); > > return 0; > + > +out: > + misc_deregister(&kni_misc); > + return rc; > } > > static void __exit > kni_exit(void) > { > + unregister_pernet_subsys(&kni_net_ops); Should above 'unregsiter' be moved after 'misc_deregister()'? > misc_deregister(&kni_misc); > KNI_PRINT("### DPDK kni module unloaded ###\n"); } @@ > -151,19 +190,22 @@ kni_parse_kthread_mode(void) static int
[dpdk-dev] [PATCH v3 5/7] virtio: virtio vec rx
> -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Huawei Xie > Sent: Tuesday, October 20, 2015 11:30 PM > To: dev at dpdk.org > Subject: [dpdk-dev] [PATCH v3 5/7] virtio: virtio vec rx > > With fixed avail ring, we don't need to get desc idx from avail ring. > virtio driver only has to deal with desc ring. > This patch uses vector instruction to accelerate processing desc ring. > > Signed-off-by: Huawei Xie > --- > drivers/net/virtio/virtio_ethdev.h | 2 + > drivers/net/virtio/virtio_rxtx.c| 3 + > drivers/net/virtio/virtio_rxtx.h| 2 + > drivers/net/virtio/virtio_rxtx_simple.c | 224 > > drivers/net/virtio/virtqueue.h | 1 + > 5 files changed, 232 insertions(+) > > diff --git a/drivers/net/virtio/virtio_ethdev.h > b/drivers/net/virtio/virtio_ethdev.h > index 9026d42..d7797ab 100644 > --- a/drivers/net/virtio/virtio_ethdev.h > +++ b/drivers/net/virtio/virtio_ethdev.h > @@ -108,6 +108,8 @@ uint16_t virtio_recv_mergeable_pkts(void *rx_queue, > struct rte_mbuf **rx_pkts, > uint16_t virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, > uint16_t nb_pkts); > > +uint16_t virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, > + uint16_t nb_pkts); > > /* > * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us > diff --git a/drivers/net/virtio/virtio_rxtx.c > b/drivers/net/virtio/virtio_rxtx.c > index 5162ce6..947fc46 100644 > --- a/drivers/net/virtio/virtio_rxtx.c > +++ b/drivers/net/virtio/virtio_rxtx.c > @@ -432,6 +432,9 @@ virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, > vq->mpool = mp; > > dev->data->rx_queues[queue_idx] = vq; > + > + virtio_rxq_vec_setup(vq); > + > return 0; > } > > diff --git a/drivers/net/virtio/virtio_rxtx.h > b/drivers/net/virtio/virtio_rxtx.h > index 7d2d8fe..831e492 100644 > --- a/drivers/net/virtio/virtio_rxtx.h > +++ b/drivers/net/virtio/virtio_rxtx.h > @@ -33,5 +33,7 @@ > > #define RTE_PMD_VIRTIO_RX_MAX_BURST 64 > > +int virtio_rxq_vec_setup(struct virtqueue *rxq); > + > int virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, > struct rte_mbuf *m); > diff --git a/drivers/net/virtio/virtio_rxtx_simple.c > b/drivers/net/virtio/virtio_rxtx_simple.c > index cac5b9f..ef17562 100644 > --- a/drivers/net/virtio/virtio_rxtx_simple.c > +++ b/drivers/net/virtio/virtio_rxtx_simple.c > @@ -58,6 +58,10 @@ > #include "virtqueue.h" > #include "virtio_rxtx.h" > > +#define RTE_VIRTIO_VPMD_RX_BURST 32 > +#define RTE_VIRTIO_DESC_PER_LOOP 8 > +#define RTE_VIRTIO_VPMD_RX_REARM_THRESH > RTE_VIRTIO_VPMD_RX_BURST > + > int __attribute__((cold)) > virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, > struct rte_mbuf *cookie) > @@ -82,3 +86,223 @@ virtqueue_enqueue_recv_refill_simple(struct > virtqueue *vq, > > return 0; > } > + > +static inline void > +virtio_rxq_rearm_vec(struct virtqueue *rxvq) > +{ > + int i; > + uint16_t desc_idx; > + struct rte_mbuf **sw_ring; > + struct vring_desc *start_dp; > + int ret; > + > + desc_idx = rxvq->vq_avail_idx & (rxvq->vq_nentries - 1); > + sw_ring = &rxvq->sw_ring[desc_idx]; > + start_dp = &rxvq->vq_ring.desc[desc_idx]; > + > + ret = rte_mempool_get_bulk(rxvq->mpool, (void **)sw_ring, > + RTE_VIRTIO_VPMD_RX_REARM_THRESH); > + if (unlikely(ret)) { > + rte_eth_devices[rxvq->port_id].data->rx_mbuf_alloc_failed += > + RTE_VIRTIO_VPMD_RX_REARM_THRESH; > + return; > + } > + > + for (i = 0; i < RTE_VIRTIO_VPMD_RX_REARM_THRESH; i++) { > + uintptr_t p; > + > + p = (uintptr_t)&sw_ring[i]->rearm_data; > + *(uint64_t *)p = rxvq->mbuf_initializer; > + > + start_dp[i].addr = > + (uint64_t)((uintptr_t)sw_ring[i]->buf_physaddr + > + RTE_PKTMBUF_HEADROOM - sizeof(struct virtio_net_hdr)); > + start_dp[i].len = sw_ring[i]->buf_len - > + RTE_PKTMBUF_HEADROOM + sizeof(struct virtio_net_hdr); > + } > + > + rxvq->vq_avail_idx += RTE_VIRTIO_VPMD_RX_REARM_THRESH; > + rxvq->vq_free_cnt -= RTE_VIRTIO_VPMD_RX_REARM_THRESH; > + vq_update_avail_idx(rxvq); > +} > + > +/* virtio vPMD receive routine, only accept(nb_pkts >= > RTE_VIRTIO_DESC_PER_LOOP) > + * > + * This routine is for non-mergable RX, one desc for each guest buffer. > + * This routine is based on the RX ring layout optimization. Each entry in > the > + * avail ring points to the desc with the same index in the desc ring and > this > + * will never be changed in the driver. > + * > + * - nb_pkts < RTE_VIRTIO_DESC_PER_LOOP, just return no packet > + */ > +uint16_t > +virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, > + uint16_t nb_pkts) > +{ > + struct virtqueue *rxvq = rx_queue; > + uint16_t nb_used; > + uint16_t desc_idx
[dpdk-dev] [PATCH] drivers: fix shared library dependencies to external libraries
On 10/21/2015 07:30 PM, Nicolas Pernas Maradei wrote: > Hi, > > Are those the only two libraries with external dependencies? I took a > quick look to the rte.app.mk file and there seem to be some others like > -lfuse and -lnuma. Would it be possible to move those to their specific > Makefiles as well? AFAICS those were only remaining *drivers* with external dependencies. The libraries have dependencies of their own like you noted, but they're more scattered, and things start getting more complicated because of CONFIG_RTE_BUILD_COMBINE_LIBS etc. I plan to get to that later when time permits but wanted to get the driver side out of the way because they're the worst offenders, and one driver already does this so the situation is inconsistent too. - Panu -
[dpdk-dev] [PATCH v3 6/7] virtio: simple tx routine
On 10/21/2015 2:58 AM, Stephen Hemminger wrote: > On Tue, 20 Oct 2015 23:30:06 +0800 > Huawei Xie wrote: > >> +desc_idx = (uint16_t)(vq->vq_used_cons_idx & >> +((vq->vq_nentries >> 1) - 1)); >> +free[0] = (struct rte_mbuf *)vq->vq_descx[desc_idx++].cookie; >> +nb_free = 1; >> + >> +for (i = 1; i < VIRTIO_TX_FREE_NR; i++) { >> +m = (struct rte_mbuf *)vq->vq_descx[desc_idx++].cookie; >> +if (likely(m->pool == free[0]->pool)) >> +free[nb_free++] = m; >> +else { >> +rte_mempool_put_bulk(free[0]->pool, (void **)free, >> +nb_free); >> +free[0] = m; >> +nb_free = 1; >> +} >> +} >> + >> +rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); > Might be better to introduce a function in rte_mbuf.h which > does this so other drivers can use same code? > > rte_pktmbuf_free_bulk(pkts[], n) Agree. It would be good to have a generic rte_pktmbuf_free(/alloc)_bulk. Several other drivers and future vhost patches also use the same logic. I prefer to implement this later as this is API change.
[dpdk-dev] [PATCH v3 5/7] virtio: virtio vec rx
On 10/22/2015 12:04 PM, Wang, Zhihong wrote: > Wonder if the prefetch will actually help here. > Will prefetching rx_pkts[i] be more helpful? What is your concern prefetch the virtio ring? rx_pkts is local array, Why do we need to prefetch it?
[dpdk-dev] dpdk proposal installation process
On 10/21/2015 10:15 PM, Olivier MATZ wrote: > Hi Mario, > > On 10/20/2015 11:17 AM, Bruce Richardson wrote: >> On Tue, Oct 20, 2015 at 12:21:00AM +, Arevalo, Mario Alfredo C wrote: >>> Hi folks, >>> >>>Good day, this is a proposal in order to improve the dpdk install >>> process, >>> I would like to know your point of view about the next points according to >>> previous conversations :) in order to create a new patches version. >>> >>> 1) I think the first thing that I have to be aware is "compatibility", the >>> new changes won't affect the current dpdk behaviour. > > Yes. As I stated in a previous mail, I think nobody uses the current > "make install" without specifying T= as the default value is to build > and install for all targets. > > My suggestion is: > > - rename the previous "install" target. The name could probably >be "mbuild" (for multiple builds). Other ideas are welcome. > > - when "make install" is invoked with T= argument, call the mbuild >target to have the same behavior than before. This compat layer >could be removed in the future. > > - when "make install" is invoked without T=, it installs the fhs. Nice, this sounds like the best of both worlds. > >>> 2) Create new makefile rules, these rules is going to install dpdk files in >>> default paths, however the linux distributions don't use the same paths for >>> their >>> files, the linux distribution and the architecture can be factor for >>> different >>> path as Panu commented in previous conversations, he is right, then all >>> variables >>> could be overridden, the variables names for the user can be included in >>> documentation. >>> Also an option could be a configuration file for paths, however I'm not >>> sure. > > I think having variables is ok. > >>> 3) The default paths for dpdk in order to follow a hierarchy, however the >>> variable >>> with those values can be overridden. >>> >>> -install-bin --> /usr/bin. >>> -install-headers --> /usr/include/dpdk >>> -install-lib --> /usr/lib64 > > I remember Panu suggested to have /usr/lib by default. > I also think /usr/lib a better default value: some distributions > use /usr/lib for 64 bits libs, but we never have 32 bits libs in > /usr/lib64. Yes, just stick /usr/lib there and be done with it, lib64 is not a good default for these very reasons. >>> -install-doc --> /usr/share/doc/dpdk >>> -install-mod--> if RTE_EXEC_ENV=linuxapp then >>> KERNEL_DIR=/lib/modules/$(uname -r)/extra/drivers/dpdk >>> else KERNEL_DIR=/boot/modules). > > I'm not sure KERNEL_DIR is the proper name. Maybe KMOD_DIR? > >>> -install-sdk --> /usr/share/dpdk and call install-headers ). >>> -install-fhs --> call install-libraries, install-mod, install-bin >>> and install-doc (maybe install-headers) >>> >>> 4) I'm going to take account all feedback about variables, paths etc for >>> the new version :). >>> >>> Thank you so much for your help. >>> >>> >>> Mario. >> >> Hi Mario, >> >> that seems like a lot of commands to add - are they all individually needed? >> >> In terms of where things go, should the "usr" part not a) be configurable via >> a parameter, and b) default to "/usr/local" as that's where user-installed >> software from outside the packaging system normally gets put. > > A PREFIX variable would do the job. > About the default to /usr or /usr/local, I agree that /usr/local looks > more usual, and I don't think it's a problem for packaging as soon as > it can be overridden. Yeah, PREFIX support would be nice, and defaulting that to /usr/local would be the right thing. - Panu - > > > Regards, > Olivier >
[dpdk-dev] [PATCH 2/5] fm10k: enable Rx queue interrupts for PF and VF
Hi, Best Regards, Mark > -Original Message- > From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Shaopeng He > Sent: Friday, September 25, 2015 1:37 PM > To: dev at dpdk.org > Subject: [dpdk-dev] [PATCH 2/5] fm10k: enable Rx queue interrupts for PF > and VF > > The patch does below things for fm10k PF and VF: > - Setup NIC to generate MSI-X interrupts > - Set the RXINT register to map interrupt causes to vectors > - Implement interrupt enable/disable functions The description is too simple, can you help to extend? Besides that, there are complicated changes in this patch. Can you help you split it to several smaller ones for better understanding? > > Signed-off-by: Shaopeng He > --- > drivers/net/fm10k/fm10k_ethdev.c | 147 > +-- > 1 file changed, 140 insertions(+), 7 deletions(-) > > diff --git a/drivers/net/fm10k/fm10k_ethdev.c > b/drivers/net/fm10k/fm10k_ethdev.c > index a82cd59..6648934 100644 > --- a/drivers/net/fm10k/fm10k_ethdev.c > +++ b/drivers/net/fm10k/fm10k_ethdev.c > > static int > +fm10k_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t > queue_id) > +{ > + struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > + > + /* Enable ITR */ > + if (hw->mac.type == fm10k_mac_pf) > + FM10K_WRITE_REG(hw, FM10K_ITR(Q2V(dev, queue_id)), > + FM10K_ITR_AUTOMASK | > FM10K_ITR_MASK_CLEAR); > + else > + FM10K_WRITE_REG(hw, FM10K_VFITR(Q2V(dev, queue_id)), > + FM10K_ITR_AUTOMASK | > FM10K_ITR_MASK_CLEAR); > + rte_intr_enable(&dev->pci_dev->intr_handle); > + return 0; > +} > + > +static int > +fm10k_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t > queue_id) > +{ > + struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > + > + /* Disable ITR */ > + if (hw->mac.type == fm10k_mac_pf) > + FM10K_WRITE_REG(hw, FM10K_ITR(Q2V(dev, queue_id)), > + FM10K_ITR_MASK_SET); > + else > + FM10K_WRITE_REG(hw, FM10K_VFITR(Q2V(dev, queue_id)), > + FM10K_ITR_MASK_SET); In previous enable function, you'll use rte_intr_enable() to enable interrupt, but You needn't disable it in this function? > + return 0; > +} > + > +static int > +fm10k_dev_rxq_interrupt_setup(struct rte_eth_dev *dev) > +{ > + struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > + struct rte_intr_handle *intr_handle = &dev->pci_dev->intr_handle; > + uint32_t intr_vector, vec; > + uint16_t queue_id; > + int result = 0; > + > + /* fm10k needs interrupt for mailbox > + * so igb_uio is not supported for rx interrupt > + */ I guess you'll support both igb_uio and VFIO, RX interrupt mode only enabled in case VFIO is used. I suggest you add more comments here for better understanding. > + if (!rte_intr_cap_multiple(intr_handle) || > + dev->data->dev_conf.intr_conf.rxq == 0) > + return result; > + > + intr_vector = dev->data->nb_rx_queues; > + > + /* disable interrupt first */ > + rte_intr_disable(&dev->pci_dev->intr_handle); > + if (hw->mac.type == fm10k_mac_pf) > + fm10k_dev_disable_intr_pf(dev); > + else > + fm10k_dev_disable_intr_vf(dev); > + > + if (rte_intr_efd_enable(intr_handle, intr_vector)) { > + PMD_INIT_LOG(ERR, "Failed to init event fd"); > + result = -EIO; > + } > + > + if (rte_intr_dp_is_en(intr_handle) && !result) { > + intr_handle->intr_vec = rte_zmalloc("intr_vec", > + dev->data->nb_rx_queues * sizeof(int), 0); > + if (intr_handle->intr_vec) { > + for (queue_id = 0, vec = RX_VEC_START; > + queue_id < dev->data- > >nb_rx_queues; > + queue_id++) { > + intr_handle->intr_vec[queue_id] = vec; > + if (vec < intr_handle->nb_efd - 1 + > RX_VEC_START) > + vec++; No "else" to handle exceptional case? > + } > + } else { > + PMD_INIT_LOG(ERR, "Failed to allocate %d > rx_queues" > + " intr_vec", dev->data->nb_rx_queues); > + result = -ENOMEM; > + } > + } > + > + if (hw->mac.type == fm10k_mac_pf) > + fm10k_dev_enable_intr_pf(dev); > + else > + fm10k_dev_enable_intr_vf(dev); > + rte_intr_enable(&dev->pci_dev->intr_handle); > + hw->mac.ops.update_int_moderator(hw); > + return result; > +} > + > +static int > fm10k_dev_handle_fault(struct fm10k_hw *hw, uint32_t eicr) > { > struct fm10k_fault fault; > @@ -2050,6 +2181,8 @@ static const struct eth_dev_ops > fm10k_eth_dev_ops = { > .tx_queue_setup = fm
[dpdk-dev] [PATCH 7/8] i40e: get_dcb_info ops implement
> -Original Message- > From: Wu, Jingjing > Sent: Thursday, September 24, 2015 2:03 PM > To: dev at dpdk.org > Cc: Wu, Jingjing; Liu, Jijiang; Zhang, Helin; Tao, Zhe; Pei, Yulong > Subject: [PATCH 7/8] i40e: get_dcb_info ops implement > > This patch implements the get_dcb_info ops in i40e driver. > > Signed-off-by: Jingjing Wu > --- > drivers/net/i40e/i40e_ethdev.c | 42 > ++ > 1 file changed, 42 insertions(+) > > diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c > index 7d252fa..76e2353 100644 > --- a/drivers/net/i40e/i40e_ethdev.c > +++ b/drivers/net/i40e/i40e_ethdev.c > @@ -220,6 +220,8 @@ static int i40e_dev_filter_ctrl(struct rte_eth_dev > *dev, > enum rte_filter_type filter_type, > enum rte_filter_op filter_op, > void *arg); > +static void i40e_dev_get_dcb_info(struct rte_eth_dev *dev, > + struct rte_eth_dcb_info *dcb_info); > static void i40e_configure_registers(struct i40e_hw *hw); static void > i40e_hw_init(struct i40e_hw *hw); static int i40e_config_qinq(struct > i40e_hw *hw, struct i40e_vsi *vsi); @@ -292,6 +294,7 @@ static const > struct eth_dev_ops i40e_eth_dev_ops = { > .timesync_disable = i40e_timesync_disable, > .timesync_read_rx_timestamp = i40e_timesync_read_rx_timestamp, > .timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp, > + .get_dcb_info = i40e_dev_get_dcb_info, > }; > > static struct eth_driver rte_i40e_pmd = { @@ -6808,3 +6811,42 @@ > i40e_dcb_setup(struct rte_eth_dev *dev) > } > return 0; > } > + > +static void > +i40e_dev_get_dcb_info(struct rte_eth_dev *dev, > + struct rte_eth_dcb_info *dcb_info) { > + struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data- > >dev_private); > + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > + struct i40e_vsi *vsi = pf->main_vsi; > + struct i40e_dcbx_config *dcb_cfg = &hw->local_dcbx_config; > + uint16_t bsf, tc_mapping; > + int i; > + > + if (dev->data->dev_conf.rxmode.mq_mode & > ETH_MQ_RX_DCB_FLAG) > + dcb_info->nb_tcs = > + dev->data- > >dev_conf.rx_adv_conf.dcb_rx_conf.nb_tcs; > + else > + dcb_info->nb_tcs = 1; > + for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) > + dcb_info->prio_tc[i] = dcb_cfg->etscfg.prioritytable[i]; > + for (i = 0; i < dcb_info->nb_tcs; i++) > + dcb_info->tc_bws[i] = dcb_cfg->etscfg.tcbwtable[i]; > + > + for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { > + if (vsi->enabled_tc & (1 << i)) { > + tc_mapping = rte_le_to_cpu_16(vsi- > >info.tc_mapping[i]); > + /* only main vsi support multi TCs */ > + dcb_info->tc_queue.tc_rxq[0][i].base = > + (tc_mapping & > I40E_AQ_VSI_TC_QUE_OFFSET_MASK) >> > + I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT; > + dcb_info->tc_queue.tc_txq[0][i].base = > + dcb_info->tc_queue.tc_rxq[0][i].base; > + bsf = (tc_mapping & > I40E_AQ_VSI_TC_QUE_NUMBER_MASK) >> > + I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT; > + dcb_info->tc_queue.tc_rxq[0][i].nb_queue = 1 << bsf; > + dcb_info->tc_queue.tc_txq[0][i].nb_queue = > + dcb_info->tc_queue.tc_rxq[0][i].nb_queue; > + } > + } > +} > -- > 2.4.0 If there are some command lines in testpmd to get DCB information, that is great.
[dpdk-dev] [PATCH v3 0/7] Support new flow director modes on Intel x550 NIC
This patch set adds 2 new flow director modes on Intel x550 NIC. The 2 new fdir modes are mac vlan mode and tunnel mode. The mac vlan mode can direct the flow based on the MAC address and VLAN TCI. The tunnel mode provides the support for VxLAN and NVGRE. x550 can recognize VxLAN and NVGRE packets, and direct the packets based on the MAC address, VLAN TCI, TNI/VNI. Surely, the MAC address, VLAN TCI, TNI/VNI can be masked, so, the flow can be directed based on the left conditions. For example, if we want to direct the flow based on the MAC address, we can use mac vlan mode with VLAN TCI masked. Now, only x550 supports these 2 modes. We should not use the new mode on other NICs. If so, the ports will not be initialized successfully. V2: Change the word 'cloud' to 'tunnel'. Change 'tni_vni' to 'tunnel_id'. V3: Change the name mac_addr_mask to mac_addr_byte_mask, for some NICs may like to support per bit mask in future. Set default VxLAN port only when the NIC support VxLAN. Make the condition more strict when check the fdir mode for avoiding the code being broken with future expansion. Make mac mask more flexible. Add a new function for MAC VLAN and tunnel mask. Wenzhuo Lu (7): lib/librte_ether: modify the structures for fdir new modes app/testpmd: initialize the new fields for fdir mask app/testpmd: new fdir modes for testpmd parameter app/testpmd: modify the output of the CLI show port fdir app/testpmd: modify and add fdir filter and mask CLIs for new modes ixgbe: implementation for fdir new modes' config doc: release notes update for flow director enhancement app/test-pmd/cmdline.c | 293 +-- app/test-pmd/config.c| 45 -- app/test-pmd/parameters.c| 7 +- app/test-pmd/testpmd.c | 3 + doc/guides/rel_notes/release_2_2.rst | 3 + drivers/net/ixgbe/ixgbe_ethdev.h | 3 + drivers/net/ixgbe/ixgbe_fdir.c | 261 +++ lib/librte_ether/rte_eth_ctrl.h | 69 ++--- 8 files changed, 606 insertions(+), 78 deletions(-) -- 1.9.3
[dpdk-dev] [PATCH v3 1/7] lib/librte_ether: modify the structures for fdir new modes
Define the new modes and modify the filter and mask structures for the mac vlan and tunnel modes. Signed-off-by: Wenzhuo Lu --- lib/librte_ether/rte_eth_ctrl.h | 69 ++--- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/lib/librte_ether/rte_eth_ctrl.h b/lib/librte_ether/rte_eth_ctrl.h index 26b7b33..078faf9 100644 --- a/lib/librte_ether/rte_eth_ctrl.h +++ b/lib/librte_ether/rte_eth_ctrl.h @@ -248,6 +248,17 @@ enum rte_eth_tunnel_type { }; /** + * Flow Director setting modes: none, signature or perfect. + */ +enum rte_fdir_mode { + RTE_FDIR_MODE_NONE = 0, /**< Disable FDIR support. */ + RTE_FDIR_MODE_SIGNATURE, /**< Enable FDIR signature filter mode. */ + RTE_FDIR_MODE_PERFECT, /**< Enable FDIR perfect filter mode for IP. */ + RTE_FDIR_MODE_PERFECT_MAC_VLAN, /**< Enable FDIR filter mode - MAC VLAN. */ + RTE_FDIR_MODE_PERFECT_TUNNEL, /**< Enable FDIR filter mode - tunnel. */ +}; + +/** * filter type of tunneling packet */ #define ETH_TUNNEL_FILTER_OMAC 0x01 /**< filter by outer MAC addr */ @@ -377,18 +388,46 @@ struct rte_eth_sctpv6_flow { }; /** + * A structure used to define the input for MAC VLAN flow + */ +struct rte_eth_mac_vlan_flow { + struct ether_addr mac_addr; /**< Mac address to match. */ +}; + +/** + * Tunnel type for flow director. + */ +enum rte_eth_fdir_tunnel_type { + RTE_FDIR_TUNNEL_TYPE_NVGRE = 0, + RTE_FDIR_TUNNEL_TYPE_VXLAN, + RTE_FDIR_TUNNEL_TYPE_UNKNOWN, +}; + +/** + * A structure used to define the input for tunnel flow, now it's VxLAN or + * NVGRE + */ +struct rte_eth_tunnel_flow { + enum rte_eth_fdir_tunnel_type tunnel_type; /**< Tunnel type to match. */ + uint32_t tunnel_id;/**< Tunnel ID to match. TNI, VNI... */ + struct ether_addr mac_addr;/**< Mac address to match. */ +}; + +/** * An union contains the inputs for all types of flow */ union rte_eth_fdir_flow { - struct rte_eth_l2_flow l2_flow; - struct rte_eth_udpv4_flow udp4_flow; - struct rte_eth_tcpv4_flow tcp4_flow; - struct rte_eth_sctpv4_flow sctp4_flow; - struct rte_eth_ipv4_flow ip4_flow; - struct rte_eth_udpv6_flow udp6_flow; - struct rte_eth_tcpv6_flow tcp6_flow; - struct rte_eth_sctpv6_flow sctp6_flow; - struct rte_eth_ipv6_flow ipv6_flow; + struct rte_eth_l2_flow l2_flow; + struct rte_eth_udpv4_flow udp4_flow; + struct rte_eth_tcpv4_flow tcp4_flow; + struct rte_eth_sctpv4_flow sctp4_flow; + struct rte_eth_ipv4_flow ip4_flow; + struct rte_eth_udpv6_flow udp6_flow; + struct rte_eth_tcpv6_flow tcp6_flow; + struct rte_eth_sctpv6_flow sctp6_flow; + struct rte_eth_ipv6_flow ipv6_flow; + struct rte_eth_mac_vlan_flow mac_vlan_flow; + struct rte_eth_tunnel_flow tunnel_flow; }; /** @@ -465,6 +504,9 @@ struct rte_eth_fdir_masks { struct rte_eth_ipv6_flow ipv6_mask; uint16_t src_port_mask; uint16_t dst_port_mask; + uint8_t mac_addr_byte_mask; /** Per byte MAC address mask */ + uint32_t tunnel_id_mask; /** tunnel ID mask */ + uint8_t tunnel_type_mask; }; /** @@ -515,15 +557,6 @@ struct rte_eth_fdir_flex_conf { /**< Flex mask configuration for each flow type */ }; -/** - * Flow Director setting modes: none, signature or perfect. - */ -enum rte_fdir_mode { - RTE_FDIR_MODE_NONE = 0, /**< Disable FDIR support. */ - RTE_FDIR_MODE_SIGNATURE, /**< Enable FDIR signature filter mode. */ - RTE_FDIR_MODE_PERFECT, /**< Enable FDIR perfect filter mode. */ -}; - #define UINT32_BIT (CHAR_BIT * sizeof(uint32_t)) #define RTE_FLOW_MASK_ARRAY_SIZE \ (RTE_ALIGN(RTE_ETH_FLOW_MAX, UINT32_BIT)/UINT32_BIT) -- 1.9.3
[dpdk-dev] [PATCH v3 2/7] app/testpmd: initialize the new fields for fdir mask
When a port is enabled, there're default values for the parameters of fdir mask. For the new parameters, the default values also need to be set. Signed-off-by: Wenzhuo Lu --- app/test-pmd/testpmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 386bf84..d34c81a 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -298,6 +298,9 @@ struct rte_fdir_conf fdir_conf = { }, .src_port_mask = 0x, .dst_port_mask = 0x, + .mac_addr_byte_mask = 0xFF, + .tunnel_type_mask = 1, + .tunnel_id_mask = 0x, }, .drop_queue = 127, }; -- 1.9.3
[dpdk-dev] [PATCH v3 4/7] app/testpmd: modify the output of the CLI show port fdir
There're fdir mask and supported flow type in the output of the CLI, show port fdir. But not every parameter has meaning for all the fdir modes, and the supported flow type is meaningless for mac vlan and tunnel modes. So, we output different thing for different mode. Signed-off-by: Wenzhuo Lu --- app/test-pmd/config.c | 45 +++-- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index cf2aa6e..1ec6a77 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1829,18 +1829,28 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) static inline void print_fdir_mask(struct rte_eth_fdir_masks *mask) { - printf("\nvlan_tci: 0x%04x, src_ipv4: 0x%08x, dst_ipv4: 0x%08x," - " src_port: 0x%04x, dst_port: 0x%04x", - mask->vlan_tci_mask, mask->ipv4_mask.src_ip, - mask->ipv4_mask.dst_ip, - mask->src_port_mask, mask->dst_port_mask); - - printf("\nsrc_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x," -" dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", - mask->ipv6_mask.src_ip[0], mask->ipv6_mask.src_ip[1], - mask->ipv6_mask.src_ip[2], mask->ipv6_mask.src_ip[3], - mask->ipv6_mask.dst_ip[0], mask->ipv6_mask.dst_ip[1], - mask->ipv6_mask.dst_ip[2], mask->ipv6_mask.dst_ip[3]); + printf("\nvlan_tci: 0x%04x, ", mask->vlan_tci_mask); + + if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) + printf("mac_addr: 0x%02x", mask->mac_addr_byte_mask); + else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) + printf("mac_addr: 0x%02x, tunnel_type: 0x%01x, tunnel_id: 0x%08x", + mask->mac_addr_byte_mask, mask->tunnel_type_mask, + mask->tunnel_id_mask); + else { + printf("src_ipv4: 0x%08x, dst_ipv4: 0x%08x," + " src_port: 0x%04x, dst_port: 0x%04x", + mask->ipv4_mask.src_ip, mask->ipv4_mask.dst_ip, + mask->src_port_mask, mask->dst_port_mask); + + printf("\nsrc_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x," + " dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x", + mask->ipv6_mask.src_ip[0], mask->ipv6_mask.src_ip[1], + mask->ipv6_mask.src_ip[2], mask->ipv6_mask.src_ip[3], + mask->ipv6_mask.dst_ip[0], mask->ipv6_mask.dst_ip[1], + mask->ipv6_mask.dst_ip[2], mask->ipv6_mask.dst_ip[3]); + } + printf("\n"); } @@ -1966,12 +1976,19 @@ fdir_get_infos(portid_t port_id) printf(" MODE: "); if (fdir_info.mode == RTE_FDIR_MODE_PERFECT) printf(" PERFECT\n"); + else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) + printf(" PERFECT-MAC-VLAN\n"); + else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) + printf(" PERFECT-TUNNEL\n"); else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE) printf(" SIGNATURE\n"); else printf(" DISABLE\n"); - printf(" SUPPORTED FLOW TYPE: "); - print_fdir_flow_type(fdir_info.flow_types_mask[0]); + if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN + && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) { + printf(" SUPPORTED FLOW TYPE: "); + print_fdir_flow_type(fdir_info.flow_types_mask[0]); + } printf(" FLEX PAYLOAD INFO:\n"); printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n" " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n" -- 1.9.3
[dpdk-dev] [PATCH v3 3/7] app/testpmd: new fdir modes for testpmd parameter
For testpmd CLI's parameter pkt-filter-mode, there're new values supported for fdir new modes, perfect-mac-vlan, perfect-tunnel. Signed-off-by: Wenzhuo Lu --- app/test-pmd/parameters.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index f1daa6e..df16e8f 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -707,12 +707,17 @@ launch_args_parse(int argc, char** argv) RTE_FDIR_MODE_SIGNATURE; else if (!strcmp(optarg, "perfect")) fdir_conf.mode = RTE_FDIR_MODE_PERFECT; + else if (!strcmp(optarg, "perfect-mac-vlan")) + fdir_conf.mode = RTE_FDIR_MODE_PERFECT_MAC_VLAN; + else if (!strcmp(optarg, "perfect-tunnel")) + fdir_conf.mode = RTE_FDIR_MODE_PERFECT_TUNNEL; else if (!strcmp(optarg, "none")) fdir_conf.mode = RTE_FDIR_MODE_NONE; else rte_exit(EXIT_FAILURE, "pkt-mode-invalid %s invalid - must be: " -"none, signature or perfect\n", +"none, signature, perfect, perfect-mac-vlan" +" or perfect-tunnel\n", optarg); } if (!strcmp(lgopts[opt_idx].name, -- 1.9.3
[dpdk-dev] [PATCH v3 5/7] app/testpmd: modify and add fdir filter and mask CLIs for new modes
The different fdir mode needs different parameters, so, the parameter *mode* is introduced to the CLI flow_director_filter and flow_director_mask. This parameter can pormpt the user to input the appropriate parameters for different mode. Please be aware, as we should set the fdir mode, the value of the parameter pkt-filter-mode, when we start testpmd. We cannot set a different mode for mask or filter. The new CLIs are added for the mac vlan and tunnel modes, like this, flow_director_mask X mode MAC-VLAN vlan mac XX, flow_director_mask X mode Tunnel vlan mac XX tunnel-type X tunnel-id , flow_director_filter X mode MAC-VLAN add/del/update mac XX:XX:XX:XX:XX:XX vlan flexbytes (X,X) fwd/drop queue X fd_id X, flow_director_filter X mode Tunnel add/del/update mac XX:XX:XX:XX:XX:XX vlan tunnel NVGRE/VxLAN tunnel-id flexbytes (X,X) fwd/drop queue X fd_id X. Signed-off-by: Wenzhuo Lu --- app/test-pmd/cmdline.c | 293 ++--- 1 file changed, 278 insertions(+), 15 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0f8f48f..ac44ab0 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -7725,6 +7725,8 @@ cmdline_parse_inst_t cmd_ethertype_filter = { struct cmd_flow_director_result { cmdline_fixed_string_t flow_director_filter; uint8_t port_id; + cmdline_fixed_string_t mode; + cmdline_fixed_string_t mode_value; cmdline_fixed_string_t ops; cmdline_fixed_string_t flow; cmdline_fixed_string_t flow_type; @@ -7747,6 +7749,12 @@ struct cmd_flow_director_result { uint16_t queue_id; cmdline_fixed_string_t fd_id; uint32_t fd_id_value; + cmdline_fixed_string_t mac; + struct ether_addr mac_addr; + cmdline_fixed_string_t tunnel; + cmdline_fixed_string_t tunnel_type; + cmdline_fixed_string_t tunnel_id; + uint32_t tunnel_id_value; }; static inline int @@ -7818,6 +7826,25 @@ str2flowtype(char *string) return RTE_ETH_FLOW_UNKNOWN; } +static uint8_t +str2fdir_tunneltype(char *string) +{ + uint8_t i = 0; + static const struct { + char str[32]; + uint8_t type; + } tunneltype_str[] = { + {"NVGRE", RTE_FDIR_TUNNEL_TYPE_NVGRE}, + {"VxLAN", RTE_FDIR_TUNNEL_TYPE_VXLAN}, + }; + + for (i = 0; i < RTE_DIM(tunneltype_str); i++) { + if (!strcmp(tunneltype_str[i].str, string)) + return tunneltype_str[i].type; + } + return RTE_FDIR_TUNNEL_TYPE_UNKNOWN; +} + #define IPV4_ADDR_TO_UINT(ip_addr, ip) \ do { \ if ((ip_addr).family == AF_INET) \ @@ -7858,6 +7885,25 @@ cmd_flow_director_filter_parsed(void *parsed_result, } memset(flexbytes, 0, sizeof(flexbytes)); memset(&entry, 0, sizeof(struct rte_eth_fdir_filter)); + + if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) { + if (strcmp(res->mode_value, "MAC-VLAN")) { + printf("Please set mode to MAC-VLAN.\n"); + return; + } + } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) { + if (strcmp(res->mode_value, "Tunnel")) { + printf("Please set mode to Tunnel.\n"); + return; + } + } else { + if (strcmp(res->mode_value, "IP")) { + printf("Please set mode to IP.\n"); + return; + } + entry.input.flow_type = str2flowtype(res->flow_type); + } + ret = parse_flexbytes(res->flexbytes_value, flexbytes, RTE_ETH_FDIR_MAX_FLEXLEN); @@ -7866,7 +7912,6 @@ cmd_flow_director_filter_parsed(void *parsed_result, return; } - entry.input.flow_type = str2flowtype(res->flow_type); switch (entry.input.flow_type) { case RTE_ETH_FLOW_FRAG_IPV4: case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: @@ -7927,9 +7972,24 @@ cmd_flow_director_filter_parsed(void *parsed_result, rte_cpu_to_be_16(res->ether_type); break; default: - printf("invalid parameter.\n"); - return; + break; + } + + if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) + (void)rte_memcpy(&entry.input.flow.mac_vlan_flow.mac_addr, +&res->mac_addr, +sizeof(struct ether_addr)); + + if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) { + (void)rte_memcpy(&entry.input.flow.tunnel_flow.mac_addr, +&res->mac_addr, +sizeof(struct ether_addr)); + entry.input.flow.tunnel_flow.tunnel_type = + st
[dpdk-dev] [PATCH v3 6/7] ixgbe: implementation for fdir new modes' config
Implement the new CLIs for fdir mac vlan and tunnel modes, including flow_director_filter and flow_director_mask. Set the mask of fdir. Add, delete or update the entities of filter. Signed-off-by: Wenzhuo Lu --- drivers/net/ixgbe/ixgbe_ethdev.h | 3 + drivers/net/ixgbe/ixgbe_fdir.c | 261 ++- 2 files changed, 234 insertions(+), 30 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h index c3d4f4f..1e971b9 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.h +++ b/drivers/net/ixgbe/ixgbe_ethdev.h @@ -133,6 +133,9 @@ struct ixgbe_hw_fdir_mask { uint16_t src_port_mask; uint16_t dst_port_mask; uint16_t flex_bytes_mask; + uint8_t mac_addr_byte_mask; + uint32_t tunnel_id_mask; + uint8_t tunnel_type_mask; }; struct ixgbe_hw_fdir_info { diff --git a/drivers/net/ixgbe/ixgbe_fdir.c b/drivers/net/ixgbe/ixgbe_fdir.c index 5c8b833..c8352f4 100644 --- a/drivers/net/ixgbe/ixgbe_fdir.c +++ b/drivers/net/ixgbe/ixgbe_fdir.c @@ -105,15 +105,23 @@ rte_memcpy((ipaddr), ipv6_addr, sizeof(ipv6_addr));\ } while (0) +#define DEFAULT_VXLAN_PORT 4789 +#define IXGBE_FDIRIP6M_INNER_MAC_SHIFT 4 + static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash); +static int fdir_set_input_mask(struct rte_eth_dev *dev, + const struct rte_eth_fdir_masks *input_mask); static int fdir_set_input_mask_82599(struct rte_eth_dev *dev, const struct rte_eth_fdir_masks *input_mask); +static int fdir_set_input_mask_x550(struct rte_eth_dev *dev, + const struct rte_eth_fdir_masks *input_mask); static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl); static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl); static int ixgbe_fdir_filter_to_atr_input( const struct rte_eth_fdir_filter *fdir_filter, - union ixgbe_atr_input *input); + union ixgbe_atr_input *input, + enum rte_fdir_mode mode); static uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input, uint32_t key); static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input *input, @@ -122,7 +130,8 @@ static uint32_t atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, enum rte_fdir_pballoc_type pballoc); static int fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, uint8_t queue, - uint32_t fdircmd, uint32_t fdirhash); + uint32_t fdircmd, uint32_t fdirhash, + enum rte_fdir_mode mode); static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw, union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd, uint32_t fdirhash); @@ -243,9 +252,16 @@ configure_fdir_flags(const struct rte_fdir_conf *conf, uint32_t *fdirctrl) *fdirctrl |= (IXGBE_DEFAULT_FLEXBYTES_OFFSET / sizeof(uint16_t)) << IXGBE_FDIRCTRL_FLEX_SHIFT; - if (conf->mode == RTE_FDIR_MODE_PERFECT) { + if (conf->mode >= RTE_FDIR_MODE_PERFECT + && conf->mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) { *fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH; *fdirctrl |= (conf->drop_queue << IXGBE_FDIRCTRL_DROP_Q_SHIFT); + if (conf->mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) + *fdirctrl |= (IXGBE_FDIRCTRL_FILTERMODE_MACVLAN + << IXGBE_FDIRCTRL_FILTERMODE_SHIFT); + else if (conf->mode == RTE_FDIR_MODE_PERFECT_TUNNEL) + *fdirctrl |= (IXGBE_FDIRCTRL_FILTERMODE_CLOUD + << IXGBE_FDIRCTRL_FILTERMODE_SHIFT); } return 0; @@ -274,7 +290,7 @@ reverse_fdir_bitmasks(uint16_t hi_dword, uint16_t lo_dword) } /* - * This is based on ixgbe_fdir_set_input_mask_82599() in base/ixgbe_82599.c, + * This references ixgbe_fdir_set_input_mask_82599() in base/ixgbe_82599.c, * but makes use of the rte_fdir_masks structure to see which bits to set. */ static int @@ -342,7 +358,6 @@ fdir_set_input_mask_82599(struct rte_eth_dev *dev, if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_SIGNATURE) { /* -* IPv6 mask is only meaningful in signature mode * Store source and destination IPv6 masks (bit reversed) */ IPV6_ADDR_TO_MASK(input_mask->ipv6_mask.src_ip, src_ipv6m); @@ -358,6 +373,122 @@ fdir_set_input_mask_82599(struct rte_eth_dev *dev, } /* + * This references ixgbe_fdir_set_input_mask_82599() in base/ixgbe_82599.c, + * but makes use of the rte_fdir_masks structure to see which bits to set. + */ +static int +fdir_set_input_mask_x550(struct rte_eth_dev *dev, + co
[dpdk-dev] [PATCH v3 7/7] doc: release notes update for flow director enhancement
Signed-off-by: Wenzhuo Lu --- doc/guides/rel_notes/release_2_2.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index bc9b00f..9d0a4d7 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -4,6 +4,9 @@ DPDK Release 2.2 New Features +* **ixgbe: flow director enhancement on Intel x550 NIC** + Add 2 new flow director mode on x550. + One is MAC VLAN mode, the other is tunnel mode. Resolved Issues --- -- 1.9.3
[dpdk-dev] [PATCH v7 4/8] vhost: rxtx: use queue id instead of constant ring index
On 10/21/2015 11:48 AM, Yuanhan Liu wrote: [...] > > #define MAX_PKT_BURST 32 > > +static inline int __attribute__((always_inline)) > +is_valid_virt_queue_idx(uint32_t virtq_idx, int is_tx, uint32_t max_qp_idx) > +{ > + if ((is_tx ^ (virtq_idx & 0x1)) || > + (virtq_idx >= max_qp_idx * VIRTIO_QNUM)) > + return 0; > + > + return 1; > +} > + > /** > * This function adds buffers to the virtio devices RX virtqueue. Buffers can > * be received from the physical port or from another virtio device. A packet > @@ -68,12 +78,14 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id, > uint8_t success = 0; > > LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh); > - if (unlikely(queue_id != VIRTIO_RXQ)) { > - LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); > + if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) { > + RTE_LOG(ERR, VHOST_DATA, > + "%s (%"PRIu64"): virtqueue idx:%d invalid.\n", > + __func__, dev->device_fh, queue_id); > return 0; > } > > - vq = dev->virtqueue[VIRTIO_RXQ]; > + vq = dev->virtqueue[queue_id]; > count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count; > > /* > Besides the always_inline issue, i think we should remove the queue_id check here in the "data" path. Caller should guarantee that they pass us the correct queue idx. We could add VHOST_DEBUG macro for the sanity check for debug purpose only. On the other hand, currently we lack of enough check for the guest because there could be malicious guests. Plan to fix this in next release. [...]
[dpdk-dev] [PATCH v2 0/2] i40e: Enlarge the number of supported queues
It enlarges the number of supported queues to hardware allowed maximum. There was a software limitation of 64 per physical port which is not reasonable. v2 changes: Fixed issues of using wrong configured number of VF queues. Helin Zhang (2): i40e: adjust the number of queues for RSS i40e: Enlarge the number of supported queues config/common_bsdapp | 3 +- config/common_linuxapp| 3 +- drivers/net/i40e/i40e_ethdev.c| 146 -- drivers/net/i40e/i40e_ethdev.h| 8 +++ drivers/net/i40e/i40e_ethdev_vf.c | 2 +- 5 files changed, 74 insertions(+), 88 deletions(-) -- 1.9.3
[dpdk-dev] [PATCH v2 1/2] i40e: adjust the number of queues for RSS
It adjusts the number of queues for RSS from power of 2 to any as long as it does not exceeds the hardware allowed. Signed-off-by: Helin Zhang --- drivers/net/i40e/i40e_ethdev.c| 8 drivers/net/i40e/i40e_ethdev_vf.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 2dd9fdc..4b70588 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -5153,12 +5153,12 @@ i40e_pf_config_rss(struct i40e_pf *pf) * If both VMDQ and RSS enabled, not all of PF queues are configured. * It's necessary to calulate the actual PF queues that are configured. */ - if (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) { + if (pf->dev_data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_VMDQ_FLAG) num = i40e_pf_calc_configured_queues_num(pf); - num = i40e_align_floor(num); - } else - num = i40e_align_floor(pf->dev_data->nb_rx_queues); + else + num = pf->dev_data->nb_rx_queues; + num = RTE_MIN(num, I40E_MAX_Q_PER_TC); PMD_INIT_LOG(INFO, "Max of contiguous %u PF queues are configured", num); diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index b694400..b15ff7b 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -1915,7 +1915,7 @@ i40evf_config_rss(struct i40e_vf *vf) return 0; } - num = i40e_align_floor(vf->dev_data->nb_rx_queues); + num = RTE_MIN(vf->dev_data->nb_rx_queues, I40E_MAX_QP_NUM_PER_VF); /* Fill out the look up table */ for (i = 0, j = 0; i < nb_q; i++, j++) { if (j >= num) -- 1.9.3
[dpdk-dev] [PATCH v2 2/2] i40e: Enlarge the number of supported queues
It enlarges the number of supported queues to hardware allowed maximum. There was a software limitation of 64 per physical port which is not reasonable. Signed-off-by: Helin Zhang --- config/common_bsdapp | 3 +- config/common_linuxapp | 3 +- drivers/net/i40e/i40e_ethdev.c | 138 + drivers/net/i40e/i40e_ethdev.h | 8 +++ 4 files changed, 69 insertions(+), 83 deletions(-) v2 changes: Fixed issues of using wrong configured number of VF queues diff --git a/config/common_bsdapp b/config/common_bsdapp index b37dcf4..dac6dad 100644 --- a/config/common_bsdapp +++ b/config/common_bsdapp @@ -141,7 +141,7 @@ CONFIG_RTE_LIBRTE_KVARGS=y CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n CONFIG_RTE_MAX_ETHPORTS=32 -CONFIG_RTE_MAX_QUEUES_PER_PORT=256 +CONFIG_RTE_MAX_QUEUES_PER_PORT=1024 CONFIG_RTE_LIBRTE_IEEE1588=n CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16 CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y @@ -187,6 +187,7 @@ CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_I40E_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n +CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4 # interval up to 8160 us, aligned to 2 (or default value) diff --git a/config/common_linuxapp b/config/common_linuxapp index 0de43d5..2ce8d66 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -139,7 +139,7 @@ CONFIG_RTE_LIBRTE_KVARGS=y CONFIG_RTE_LIBRTE_ETHER=y CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n CONFIG_RTE_MAX_ETHPORTS=32 -CONFIG_RTE_MAX_QUEUES_PER_PORT=256 +CONFIG_RTE_MAX_QUEUES_PER_PORT=1024 CONFIG_RTE_LIBRTE_IEEE1588=n CONFIG_RTE_ETHDEV_QUEUE_STAT_CNTRS=16 CONFIG_RTE_ETHDEV_RXTX_CALLBACKS=y @@ -185,6 +185,7 @@ CONFIG_RTE_LIBRTE_I40E_DEBUG_TX_FREE=n CONFIG_RTE_LIBRTE_I40E_DEBUG_DRIVER=n CONFIG_RTE_LIBRTE_I40E_RX_ALLOW_BULK_ALLOC=y CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC=n +CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF=64 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF=4 CONFIG_RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM=4 # interval up to 8160 us, aligned to 2 (or default value) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 4b70588..8928b0a 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -2240,113 +2240,88 @@ i40e_pf_parameter_init(struct rte_eth_dev *dev) { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct i40e_hw *hw = I40E_PF_TO_HW(pf); - uint16_t sum_queues = 0, sum_vsis, left_queues; + uint16_t qp_count = 0, vsi_count = 0; - /* First check if FW support SRIOV */ if (dev->pci_dev->max_vfs && !hw->func_caps.sr_iov_1_1) { PMD_INIT_LOG(ERR, "HW configuration doesn't support SRIOV"); return -EINVAL; } pf->flags = I40E_FLAG_HEADER_SPLIT_DISABLED; - pf->max_num_vsi = RTE_MIN(hw->func_caps.num_vsis, I40E_MAX_NUM_VSIS); - PMD_INIT_LOG(INFO, "Max supported VSIs:%u", pf->max_num_vsi); - /* Allocate queues for pf */ - if (hw->func_caps.rss) { - pf->flags |= I40E_FLAG_RSS; - pf->lan_nb_qps = RTE_MIN(hw->func_caps.num_tx_qp, - (uint32_t)(1 << hw->func_caps.rss_table_entry_width)); - pf->lan_nb_qps = i40e_align_floor(pf->lan_nb_qps); - } else + pf->max_num_vsi = hw->func_caps.num_vsis; + pf->lan_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_PF; + pf->vmdq_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM; + pf->vf_nb_qp_max = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF; + + /* FDir queue/VSI allocation */ + pf->fdir_qp_offset = 0; + if (hw->func_caps.fd) { + pf->flags |= I40E_FLAG_FDIR; + pf->fdir_nb_qps = I40E_DEFAULT_QP_NUM_FDIR; + } else { + pf->fdir_nb_qps = 0; + } + qp_count += pf->fdir_nb_qps; + vsi_count += 1; + + /* LAN queue/VSI allocation */ + pf->lan_qp_offset = pf->fdir_qp_offset + pf->fdir_nb_qps; + if (!hw->func_caps.rss) { pf->lan_nb_qps = 1; - sum_queues = pf->lan_nb_qps; - /* Default VSI is not counted in */ - sum_vsis = 0; - PMD_INIT_LOG(INFO, "PF queue pairs:%u", pf->lan_nb_qps); + } else { + pf->flags |= I40E_FLAG_RSS; + pf->lan_nb_qps = pf->lan_nb_qp_max; + } + qp_count += pf->lan_nb_qps; + vsi_count += 1; + /* VF queue/VSI allocation */ + pf->vf_qp_offset = pf->lan_qp_offset + pf->lan_nb_qps; if (hw->func_caps.sr_iov_1_1 && dev->pci_dev->max_vfs) { pf->flags |= I40E_FLAG_SRIOV; pf->vf_nb_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VF; - if (dev->pci_dev->max_vfs > hw->func_caps.num_vfs) { - PMD_INIT_LOG(ERR, "Config VF number %u, " -"max sup
[dpdk-dev] [PATCH v2] ixgbe: Drop flow control frames from VFs
This patch will drop flow control frames from being transmitted from VSIs. With this patch in place a malicious VF cannot send flow control or PFC packets out on the wire. V2: Reword the comments. Signed-off-by: Wenzhuo Lu --- drivers/net/ixgbe/ixgbe_pf.c | 43 +++ 1 file changed, 43 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_pf.c b/drivers/net/ixgbe/ixgbe_pf.c index fd1c4ca..b33f4e9 100644 --- a/drivers/net/ixgbe/ixgbe_pf.c +++ b/drivers/net/ixgbe/ixgbe_pf.c @@ -55,6 +55,7 @@ #define IXGBE_MAX_VFTA (128) #define IXGBE_VF_MSG_SIZE_DEFAULT 1 #define IXGBE_VF_GET_QUEUE_MSG_SIZE 5 +#define IXGBE_ETHERTYPE_FLOW_CTRL 0x8808 static inline uint16_t dev_num_vf(struct rte_eth_dev *eth_dev) @@ -166,6 +167,46 @@ void ixgbe_pf_host_uninit(struct rte_eth_dev *eth_dev) *vfinfo = NULL; } +static void +ixgbe_add_tx_flow_control_drop_filter(struct rte_eth_dev *eth_dev) +{ + struct ixgbe_hw *hw = + IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); + struct ixgbe_filter_info *filter_info = + IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); + uint16_t vf_num; + int i; + + /* occupy an entity of ether type filter */ + for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) { + if (!(filter_info->ethertype_mask & (1 << i))) { + filter_info->ethertype_mask |= 1 << i; + filter_info->ethertype_filters[i] = + IXGBE_ETHERTYPE_FLOW_CTRL; + break; + } + } + if (i == IXGBE_MAX_ETQF_FILTERS) { + RTE_LOG(ERR, PMD, "Cannot find an unused ether type filter" + " entity for flow control.\n"); + return; + } + + if (hw->mac.ops.set_ethertype_anti_spoofing) { + IXGBE_WRITE_REG(hw, IXGBE_ETQF(i), + (IXGBE_ETQF_FILTER_EN | + IXGBE_ETQF_TX_ANTISPOOF | + IXGBE_ETHERTYPE_FLOW_CTRL)); + + vf_num = dev_num_vf(eth_dev); + for (i = 0; i < vf_num; i++) { + hw->mac.ops.set_ethertype_anti_spoofing(hw, true, i); + } + } + + return; +} + int ixgbe_pf_host_configure(struct rte_eth_dev *eth_dev) { uint32_t vtctl, fcrth; @@ -262,6 +303,8 @@ int ixgbe_pf_host_configure(struct rte_eth_dev *eth_dev) IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); } + ixgbe_add_tx_flow_control_drop_filter(eth_dev); + return 0; } -- 1.9.3
[dpdk-dev] ixgbe: ierrors counter spuriously increasing in DPDK 2.1
Hi Andriy, thank you for pointing this discussion out to me. I somehow missed it. Unfortunately it looks like the discussion stopped after Maryam made a good proposal so I will vote in on that and hopefully get things started again. Best regards, Martin On 21.10.15 17:53, Andriy Berestovskyy wrote: > Yes Marcin, > The issue was discussed here: > http://dpdk.org/ml/archives/dev/2015-September/023229.html > > You can either fix the ierrors in ixgbe_dev_stats_get() or implement a > workaround in your app getting the extended statistics and counting > out some of extended counters from the ierrors. > > Here is an example: > https://github.com/Juniper/contrail-vrouter/commit/72f6ca05ac81d0ca5e7eb93c6ffe7a93648c2b00#diff-99c1f65a00658c7d38b3d1b64cb5fd93R1306 > > Regards, > Andriy > > On Wed, Oct 21, 2015 at 10:38 AM, Martin Weiser > wrote: >> Hi, >> >> with DPDK 2.1 we are seeing the ierrors counter increasing for 82599ES >> ports without reason. Even directly after starting test-pmd the error >> counter immediately is 1 without even a single packet being sent to the >> device: >> >> ./testpmd -c 0xfe -n 4 -- --portmask 0x3 --interactive >> ... >> testpmd> show port stats all >> >> NIC statistics for port 0 >> >> RX-packets: 0 RX-missed: 0 RX-bytes: 0 >> RX-badcrc: 0 RX-badlen: 0 RX-errors: 1 >> RX-nombuf: 0 >> TX-packets: 0 TX-errors: 0 TX-bytes: 0 >> >> >> >> NIC statistics for port 1 >> >> RX-packets: 0 RX-missed: 0 RX-bytes: 0 >> RX-badcrc: 0 RX-badlen: 0 RX-errors: 1 >> RX-nombuf: 0 >> TX-packets: 0 TX-errors: 0 TX-bytes: 0 >> >> >> >> >> When packet forwarding is started the ports perform normally and >> properly forward all packets but a huge number of ierrors is counted: >> >> testpmd> start >> ... >> testpmd> show port stats all >> >> NIC statistics for port 0 >> >> RX-packets: 9011857RX-missed: 0 RX-bytes: 5020932992 >> RX-badcrc: 0 RX-badlen: 0 RX-errors: 9011753 >> RX-nombuf: 0 >> TX-packets: 9026250TX-errors: 0 TX-bytes: 2922375542 >> >> >> >> NIC statistics for port 1 >> >> RX-packets: 9026250RX-missed: 0 RX-bytes: 2922375542 >> RX-badcrc: 0 RX-badlen: 0 RX-errors: 9026138 >> RX-nombuf: 0 >> TX-packets: 9011857TX-errors: 0 TX-bytes: 5020932992 >> >> >> >> >> When running the exact same test with DPDK version 2.0 no ierrors are >> reported. >> Is anyone else seeing strange ierrors being reported for Intel Niantic >> cards with DPDK 2.1? >> >> Best regards, >> Martin >> > >
[dpdk-dev] [PATCH v4 0/2] e1000: enable igb TSO support
Hi, > -Original Message- > From: Wang, Xiao W > Sent: Wednesday, October 21, 2015 3:55 PM > To: dev at dpdk.org > Cc: Lu, Wenzhuo; Richardson, Bruce; Zhang, Helin; Wang, Xiao W > Subject: [PATCH v4 0/2] e1000: enable igb TSO support > > v4: > * Added ULL postfix to compare mask of igb_tx_offload. > > v3: > * Removed the "unlikely" in check_tso_para function, for there was no > obvious performance > difference, let the branch predictor do the job. > > v2: > * Reworded the old comment about union igb_vlan_macip which was no > more used. > > * Corrected typo in line "There're some limitaions in hardware for TCP > segmentaion offload". > > * Added "unlikely" in check_tso_para function. > > v1: > * Initial version for igb TSO feature. > > Wang Xiao W (2): > e1000: enable igb TSO support > doc: update release note for igb TSO support > > doc/guides/rel_notes/release_2_2.rst | 4 + > drivers/net/e1000/igb_ethdev.c | 6 +- > drivers/net/e1000/igb_rxtx.c | 200 > +-- > 3 files changed, 131 insertions(+), 79 deletions(-) > > -- > 1.9.3 Acked-by: Wenzhuo Lu
[dpdk-dev] i40e: problem with rx packet drops not accounted in statistics
Hi Helin, good to know that there is work being done on that issue. By performance problem I mean that theses packet discards start to appear at low bandwidths where I would not expect any packets to be dropped. On the same system we can reach higher bandwidths using ixgbe NICs without loosing a single packet so seeing packets being lost at only ~5GBit/s and ~1.5Mpps on a 40Gb adapter worries me a bit. Best regards, Martin On 22.10.15 02:16, Zhang, Helin wrote: > Hi Martin > > Yes, we have a developer working on it now, and hopefully he will have > something soon later on this fix. > But what do you mean the performance problem? Did you mean the performance > number is not good as expected, or else? > > Regards, > Helin > >> -Original Message- >> From: Martin Weiser [mailto:martin.weiser at allegro-packets.com] >> Sent: Wednesday, October 21, 2015 4:44 PM >> To: Zhang, Helin >> Cc: dev at dpdk.org >> Subject: Re: i40e: problem with rx packet drops not accounted in statistics >> >> Hi Helin, >> >> any news on this issue? By the way this is not just a problem with >> statistics for us >> but also a performance problem since these packet discards start appearing >> at a >> relatively low bandwidth (~5GBit/s and ~1.5Mpps). >> >> Best regards, >> Martin >> >> On 10.09.15 03:09, Zhang, Helin wrote: >>> Hi Martin >>> >>> Yes, the statistics issue has been reported several times recently. >>> We will check the issue and try to fix it or get a workaround soon. Thank >>> you >> very much! >>> Regards, >>> Helin >>> -Original Message- From: Martin Weiser [mailto:martin.weiser at allegro-packets.com] Sent: Wednesday, September 9, 2015 7:58 PM To: Zhang, Helin Cc: dev at dpdk.org Subject: i40e: problem with rx packet drops not accounted in statistics Hi Helin, in one of our test setups involving i40e adapters we are experiencing packet drops which are not reflected in the interfaces statistics. The call to rte_eth_stats_get suggests that all packets were properly received but the total number of packets received through rte_eth_rx_burst is less than the ipackets counter. When for example running the l2fwd application (l2fwd -c 0xfe -n 4 -- -p 0x3) and having driver debug messages enabled the following output is generated for the interface in question: ... PMD: i40e_update_vsi_stats(): * VSI[6] stats start *** PMD: i40e_update_vsi_stats(): rx_bytes:24262434 PMD: i40e_update_vsi_stats(): rx_unicast: 16779 PMD: i40e_update_vsi_stats(): rx_multicast:0 PMD: i40e_update_vsi_stats(): rx_broadcast:0 PMD: i40e_update_vsi_stats(): rx_discards: 1192557 PMD: i40e_update_vsi_stats(): rx_unknown_protocol: 0 PMD: i40e_update_vsi_stats(): tx_bytes:0 PMD: i40e_update_vsi_stats(): tx_unicast: 0 PMD: i40e_update_vsi_stats(): tx_multicast:0 PMD: i40e_update_vsi_stats(): tx_broadcast:0 PMD: i40e_update_vsi_stats(): tx_discards: 0 PMD: i40e_update_vsi_stats(): tx_errors: 0 PMD: i40e_update_vsi_stats(): * VSI[6] stats end *** PMD: i40e_dev_stats_get(): * PF stats start *** PMD: i40e_dev_stats_get(): rx_bytes:24262434 PMD: i40e_dev_stats_get(): rx_unicast: 16779 PMD: i40e_dev_stats_get(): rx_multicast:0 PMD: i40e_dev_stats_get(): rx_broadcast:0 PMD: i40e_dev_stats_get(): rx_discards: 0 PMD: i40e_dev_stats_get(): rx_unknown_protocol: 16779 PMD: i40e_dev_stats_get(): tx_bytes:0 PMD: i40e_dev_stats_get(): tx_unicast: 0 PMD: i40e_dev_stats_get(): tx_multicast:0 PMD: i40e_dev_stats_get(): tx_broadcast:0 PMD: i40e_dev_stats_get(): tx_discards: 0 PMD: i40e_dev_stats_get(): tx_errors: 0 PMD: i40e_dev_stats_get(): tx_dropped_link_down: 0 PMD: i40e_dev_stats_get(): crc_errors: 0 PMD: i40e_dev_stats_get(): illegal_bytes:0 PMD: i40e_dev_stats_get(): error_bytes: 0 PMD: i40e_dev_stats_get(): mac_local_faults: 1 PMD: i40e_dev_stats_get(): mac_remote_faults:1 PMD: i40e_dev_stats_get(): rx_length_errors: 0 PMD: i40e_dev_stats_get(): link_xon_rx: 0 PMD: i40e_dev_stats_get(): link_xoff_rx: 0 PMD: i40e_dev_stats_get(): priority_xon_rx[0]: 0 PMD: i40e_dev_stats_get(): priority_xoff_rx[0]: 0 PMD: i40e_dev_stats_get(): priority_xon_rx[1]: 0 PMD: i40e_dev_stats_get(): priority_xoff_rx[1]: 0 PMD: i40e_dev_stats_get(): priority_xon_rx[2]: 0 PMD: i40e_dev_stats_get(): priority_xoff_rx[2]: 0 >>
[dpdk-dev] volunteer to be the maintainer of driver/net/intel sub-tree
Hi Wenzhuo, 2015-10-22 02:49, Lu, Wenzhuo: > Hi all, > Following the discussion of DPDK user space and the maintenance of > development sub-trees, I'd like to volunteer myself to be the maintainer of > sub-tree driver/net/intel. It includes all the PMD of Intel NICs. And Helin > can be my backup. Thanks for proposing. You are already doing part of the work being maintainer of e1000, and Helin for ixgbe and i40e. > I suggest we create a new directory to move the driver/net/e1000, > driver/net/fm10k... to it. And we can also create directories for other > vendors just like the kernel driver do. We don't need to move files to be able to manage them in a sub-tree. For the day to day tasks, it's better to limit directory depth. And think about what happened with Broadcom and Qlogic, we are not going to move files when Intel will buy the NIC xyz. Generally speaking, it's better to keep company names outside of technical things. > Additionally, as we observed, some patch sets will not only change the files > in drivers/net, but also some files in lib/librte_ether, doc, app, > examples... Only being drivers/net/intel maintainer cannot work for these > patch sets, especially for the new features. Applying partial feature patch > set is not ideal. Ideally we need a maintainer to drive the RTE_ETHER > discussion. Maybe Bruce can be a top-level maintainer. So, he can help when > we face this scenario. A sub-tree is not restricted to some directories. It must manage an expertise zone, a technical domain, an area of interest, choose your words ;) Today we have no working sub-tree. So we should start splitting areas in some large grain and make it work. Then we can split more with a top down approach. So I think we should first create the subtree for networking drivers and wait a little before having a subtree for Intel NICs. Do you agree?
[dpdk-dev] ixgbe: account more Rx errors Issue
On 14.09.15 11:50, Tahhan, Maryam wrote: >> From: Kyle Larose [mailto:eomereadig at gmail.com] >> Sent: Wednesday, September 9, 2015 6:43 PM >> To: Tahhan, Maryam >> Cc: Olivier MATZ; Andriy Berestovskyy; dev at dpdk.org >> Subject: Re: [dpdk-dev] ixgbe: account more Rx errors Issue >> >> >> On Mon, Sep 7, 2015 at 7:44 AM, Tahhan, Maryam >> wrote: >>> From: Olivier MATZ [mailto:olivier.matz at 6wind.com] >>> Sent: Monday, September 7, 2015 9:30 AM >>> To: Tahhan, Maryam; Andriy Berestovskyy >>> Cc: dev at dpdk.org >>> Subject: Re: ixgbe: account more Rx errors Issue >>> >>> Hi, >>> >>> On 09/06/2015 07:15 PM, Tahhan, Maryam wrote: > From: Andriy Berestovskyy [mailto:aber at semihalf.com] > Sent: Friday, September 4, 2015 5:59 PM > To: Tahhan, Maryam > Cc: dev at dpdk.org; Olivier MATZ > Subject: Re: ixgbe: account more Rx errors Issue > > Hi Maryam, > Please see below. > >> XEC counts the Number of receive IPv4, TCP, UDP or SCTP XSUM errors > Please note than UDP checksum is optional for IPv4, but UDP packets > with zero checksum hit XEC. > I understand, but this is what the hardware register is picking up and what I >>> included previously is the definitions of the registers from the datasheet. >> And general crc errors counts Counts the number of receive packets >> with > CRC errors. > > Let me explain you with an example. > > DPDK 2.0 behavior: > host A sends 10M IPv4 UDP packets (no checksum) to host B host B > stats: 9M ipackets + 1M ierrors (missed) = 10M > > DPDK 2.1 behavior: > host A sends 10M IPv4 UDP packets (no checksum) to host B host B > stats: 9M ipackets + 11M in ierrors (1M missed + 10M XEC) = 20M? Because it's hitting the 2 error registers. If you had packets with multiple >>> errors that are added up as part of ierrors you'll still be getting more >>> than >>> 10M errors which is why I asked for feedback on the 3 suggestions below. >>> What I'm saying is the number of errors being > the number of received >>> packets will be seen if you hit multiple error registers on the NIC. >> So our options are we can: >> 1. Add only one of these into the error stats. >> 2. We can introduce some cooking of stats in this scenario, so only >> add > either or if they are equal or one is higher than the other. >> 3. Add them all which means you can have more errors than the number >> of > received packets, but TBH this is going to be the case if your > packets have multiple errors anyway. > > 4. ierrors should reflect NIC drops only. I may have misinterpreted this, but ierrors in rte_ethdev.h ierrors is defined >>> as the Total number of erroneous received packets. Maybe we need a clear definition or a separate drop counter as I see >>> uint64_t q_errors defined as: Total number of queue packets received that >>> are dropped. > XEC does not count drops, so IMO it should be removed from ierrors. While it's picking up the 0 checksum as an error (which it shouldn't necessarily be doing), removing it could mean missing other valid L3/L4 checksum errors... Let me experiment some more with L3/L4 checksum errors and crcerrs to see if we can cook the stats around this register in particular. I would hate to remove it and miss genuine errors >>> For me, the definition that looks the most straightforward is: >>> >>> ipackets = packets successfully received by hardware imissed = packets >>> dropped by hardware because the software does >>>not poll fast enough (= queue full) >>> ierrors = packets dropped by hardware (malformed packets, ...) >>> >>> These 3 stats never count twice the same packet. >>> >>> If we want more statistics, they could go in xstats. For instance, a >>> counter for >>> invalid checksum. The definition of these stats would be pmd-specific. >>> >>> I agree we should clarify and have a consensus on the definitions before >>> going >>> further. >>> >>> >>> Regards, >>> Olivier >> Hi Olivier >> I think it's important to distinguish between errors and drops and provide a >> statistics API that exposes both. This way people have access to as much >> information as possible when things do go wrong and nothing is missed in >> terms of errors. >> >> My suggestion for the high level registers would be: >> ipackets = Total number of packets successfully received by hardware >> imissed = Total number of packets dropped by hardware because the software >> does not poll fast enough (= queue full) >> idrops = Total number of packets dropped by hardware (malformed packets, >> ...) Where the # of drops can ONLY be <= the packets received (without >> overlap between registers). >> ierrors = Total number of erroneous received packets. Where the # of errors >> can be >= the packets received (without overlap between registers), this is >> because there may be multiple errors ass
[dpdk-dev] [PATCH v3 0/7] Support new flow director modes on Intel x550 NIC
> -Original Message- > From: Lu, Wenzhuo > Sent: Thursday, October 22, 2015 8:12 AM > To: dev at dpdk.org > Cc: Ananyev, Konstantin > Subject: [PATCH v3 0/7] Support new flow director modes on Intel x550 NIC > > This patch set adds 2 new flow director modes on Intel x550 NIC. > The 2 new fdir modes are mac vlan mode and tunnel mode. > The mac vlan mode can direct the flow based on the MAC address and VLAN > TCI. > The tunnel mode provides the support for VxLAN and NVGRE. x550 can recognize > VxLAN and NVGRE packets, and direct the packets based on the MAC address, > VLAN TCI, TNI/VNI. > Surely, the MAC address, VLAN TCI, TNI/VNI can be masked, so, the flow > can be directed based on the left conditions. For example, if we want to > direct the flow based on the MAC address, we can use mac vlan mode with > VLAN TCI masked. > Now, only x550 supports these 2 modes. We should not use the new mode on > other NICs. If so, the ports will not be initialized successfully. > > V2: > Change the word 'cloud' to 'tunnel'. > Change 'tni_vni' to 'tunnel_id'. > > V3: > Change the name mac_addr_mask to mac_addr_byte_mask, for some NICs may like > to support per bit mask in future. > Set default VxLAN port only when the NIC support VxLAN. > Make the condition more strict when check the fdir mode for avoiding the code > being broken with future expansion. > Make mac mask more flexible. > Add a new function for MAC VLAN and tunnel mask. > > > Wenzhuo Lu (7): > lib/librte_ether: modify the structures for fdir new modes > app/testpmd: initialize the new fields for fdir mask > app/testpmd: new fdir modes for testpmd parameter > app/testpmd: modify the output of the CLI show port fdir > app/testpmd: modify and add fdir filter and mask CLIs for new modes > ixgbe: implementation for fdir new modes' config > doc: release notes update for flow director enhancement > > app/test-pmd/cmdline.c | 293 > +-- > app/test-pmd/config.c| 45 -- > app/test-pmd/parameters.c| 7 +- > app/test-pmd/testpmd.c | 3 + > doc/guides/rel_notes/release_2_2.rst | 3 + > drivers/net/ixgbe/ixgbe_ethdev.h | 3 + > drivers/net/ixgbe/ixgbe_fdir.c | 261 +++ > lib/librte_ether/rte_eth_ctrl.h | 69 ++--- > 8 files changed, 606 insertions(+), 78 deletions(-) > > -- Acked-by: Konstantin Ananyev > 1.9.3
[dpdk-dev] [PATCH v3] mem: command line option to delete hugepage backing files
On 21/10/2015 17:34, Bruce Richardson wrote: > On Wed, Oct 21, 2015 at 04:22:45PM +, shesha Sreenivasamurthy (shesha) > wrote: >> When an application using huge-pages crash or exists, the hugetlbfs >> backing files are not cleaned up. This is a patch to clean those files. >> There are multi-process DPDK applications that may be benefited by those >> backing files. Therefore, I have made that configurable so that the >> application that does not need those backing files can remove them, thus >> not changing the current default behavior. The application itself can >> clean it up, however the rationale behind DPDK cleaning it up is, DPDK >> created it and therefore, it is better it unlinks it. >> >> Signed-off-by: Shesha Sreenivasamurthy >> --- >> lib/librte_eal/common/eal_common_options.c | 12 >> lib/librte_eal/common/eal_internal_cfg.h | 1 + >> lib/librte_eal/common/eal_options.h| 2 ++ >> lib/librte_eal/linuxapp/eal/eal_memory.c | 30 >> ++ >> 4 files changed, 45 insertions(+) >> > >> +static int >> +unlink_hugepage_files(struct hugepage_file *hugepg_tbl, >> +unsigned num_hp_info) >> +{ >> +unsigned socket, size; >> +int page, nrpages = 0; >> + >> +/* get total number of hugepages */ >> +for (size = 0; size < num_hp_info; size++) >> +for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) >> +nrpages += >> internal_config.hugepage_info[size].num_pages[socket]; >> + >> +for (page = 0; page < nrpages; page++) { >> +struct hugepage_file *hp = &hugepg_tbl[page]; >> +if (hp->final_va != NULL && unlink(hp->filepath)) { >> +RTE_LOG(WARNING, EAL, "%s(): Removing %s failed: %s\n", >> +__func__, hp->filepath, strerror(errno)); >> +} >> +} >> +return 0; >> +} >> + >> /* >>* unmaps hugepages that are not going to be used. since we originally >> allocate >>* ALL hugepages (not just those we need), additional unmapping needs to >> be done. >> @@ -1289,6 +1311,14 @@ rte_eal_hugepage_init(void) >> goto fail; >> } >> >> +/* free the hugepage backing files */ >> +if (internal_config.hugepage_unlink && >> +unlink_hugepage_files(tmp_hp, >> +internal_config.num_hugepage_sizes) < 0) { >> +RTE_LOG(ERR, EAL, "Unlinking hugepage backing files >> failed!\n"); >> +goto fail; >> +} >> + > Sorry for the late comment, but... > > Rather than adding a whole new function to be called here, can the same effect > not be got by adding in 2/3 lines like: > if (internal_config.hugepage_unlink) > unlink(hugetlb[i].filepath) > > at line 409 of eal_memory.c where were have done our final mmap of the file. > [You also need the same couple of lines for the 32-bit special case at line > 351]. > It would be a shorter diff. > > /Bruce If you wanted to avoid the extra function call, I might be cleaner to just unlink all files when doing unmap_all_hugepages_orig. My two cents: I think it would be easier to read/debug having a function that "unlinks files" instead of unlinking files at different points in map_all_hugepages. Unfortunately the proposed approach does not work for all cases: - If we have single file segment, map_all_hugepages does not get call a second time, instead we call remap_all_hugepages - If we use options -m or --socket-mem, because unmap_unneeded_hugepages does not expect files already unlinked, it will fail when trying to unlink unneeded hugepage files. The current patch would work as we only unlink after unmap_unneeded_hugepages. Sergio
[dpdk-dev] [PATCH v4] mem: command line option to delete hugepage backing files
On 21/10/2015 18:21, shesha Sreenivasamurthy (shesha) wrote: > When an application using huge-pages crash or exists, the hugetlbfs > backing files are not cleaned up. This is a patch to clean those files. > There are multi-process DPDK applications that may be benefited by those > backing files. Therefore, I have made that configurable so that the > application that does not need those backing files can remove them, thus > not changing the current default behavior. The application itself can > clean it up, however the rationale behind DPDK cleaning it up is, DPDK > created it and therefore, it is better it unlinks it. > > > Signed-off-by: Shesha Sreenivasamurthy > --- > lib/librte_eal/common/eal_common_options.c | 12 > lib/librte_eal/common/eal_internal_cfg.h | 1 + > lib/librte_eal/common/eal_options.h| 2 ++ > lib/librte_eal/linuxapp/eal/eal_memory.c | 12 > 4 files changed, 27 insertions(+) > > diff --git a/lib/librte_eal/common/eal_common_options.c > b/lib/librte_eal/common/eal_common_options.c > index 1f459ac..5fe6374 100644 > --- a/lib/librte_eal/common/eal_common_options.c > +++ b/lib/librte_eal/common/eal_common_options.c > @@ -79,6 +79,7 @@ eal_long_options[] = { > {OPT_MASTER_LCORE, 1, NULL, OPT_MASTER_LCORE_NUM }, > {OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM }, > {OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM }, > + {OPT_HUGE_UNLINK, 0, NULL, OPT_HUGE_UNLINK_NUM }, > {OPT_NO_PCI,0, NULL, OPT_NO_PCI_NUM }, > {OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM}, > {OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM}, > @@ -722,6 +723,10 @@ eal_parse_common_option(int opt, const char *optarg, > conf->no_hugetlbfs = 1; > break; > > + case OPT_HUGE_UNLINK_NUM: > + conf->hugepage_unlink = 1; > + break; > + > case OPT_NO_PCI_NUM: > conf->no_pci = 1; > break; > @@ -856,6 +861,12 @@ eal_check_common_options(struct internal_config > *internal_cfg) > return -1; > } > > + if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) { > + RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot " > + "be specified together with --"OPT_NO_HUGE"\n"); > + return -1; > + } > + > if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 && > rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) { > RTE_LOG(ERR, EAL, "Options blacklist (-b) and whitelist (-w) " > @@ -906,6 +917,7 @@ eal_common_usage(void) > " -h, --help This help\n" > "\nEAL options for DEBUG use only:\n" > " --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n" > +" --"OPT_HUGE_UNLINK" Unlink hugepage backing file after > initalization\n" The line above (and a couple more in the patch) is getting wrapped, causing checkpatch to report errors and git failing to apply the patch. > " --"OPT_NO_PCI"Disable PCI\n" > " --"OPT_NO_HPET" Disable HPET\n" > " --"OPT_NO_SHCONF" No shared config (mmap'd files)\n" > diff --git a/lib/librte_eal/common/eal_internal_cfg.h > b/lib/librte_eal/common/eal_internal_cfg.h > index e2ecb0d..84b075f 100644 > --- a/lib/librte_eal/common/eal_internal_cfg.h > +++ b/lib/librte_eal/common/eal_internal_cfg.h > @@ -64,6 +64,7 @@ struct internal_config { > volatile unsigned force_nchannel; /**< force number of channels */ > volatile unsigned force_nrank;/**< force number of ranks */ > volatile unsigned no_hugetlbfs; /**< true to disable hugetlbfs */ > + volatile unsigned hugepage_unlink; /** < true to unlink backing files */ > volatile unsigned xen_dom0_support; /**< support app running on Xen > Dom0*/ > volatile unsigned no_pci; /**< true to disable PCI */ > volatile unsigned no_hpet;/**< true to disable HPET */ > diff --git a/lib/librte_eal/common/eal_options.h > b/lib/librte_eal/common/eal_options.h > index f6714d9..745f38c 100644 > --- a/lib/librte_eal/common/eal_options.h > +++ b/lib/librte_eal/common/eal_options.h > @@ -63,6 +63,8 @@ enum { > OPT_PROC_TYPE_NUM, > #define OPT_NO_HPET "no-hpet" > OPT_NO_HPET_NUM, > +#define OPT_HUGE_UNLINK"huge-unlink" > + OPT_HUGE_UNLINK_NUM, > #define OPT_NO_HUGE "no-huge" > OPT_NO_HUGE_NUM, > #define OPT_NO_PCI"no-pci" > diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c > b/lib/librte_eal/linuxapp/eal/eal_memory.c > index ac2745e..c6f383b 100644 > --- a/lib/librte_eal/linuxapp/eal/eal_memory.c > +++ b/lib/librte_eal/linuxapp/eal/eal_memory.c > @@ -348,6 +348,12 @@ map_all_hugepages(struct hugepage_file *hugepg_tbl, >
[dpdk-dev] [PATCH v7 2/8] vhost-user: add VHOST_USER_GET_QUEUE_NUM message
On 10/21/2015 11:48 AM, Yuanhan Liu wrote: > To tell the frontend (qemu) how many queue pairs we support. > > And it is initiated to VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX. s/initiated/initialized/
[dpdk-dev] [PATCH v2 01/16] fm10k: add new vPMD file
From: "Chen Jing D(Mark)" Add new file fm10k_rxtx_vec.c and add it into compiling. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/Makefile |1 + drivers/net/fm10k/fm10k_rxtx_vec.c | 45 2 files changed, 46 insertions(+), 0 deletions(-) create mode 100644 drivers/net/fm10k/fm10k_rxtx_vec.c diff --git a/drivers/net/fm10k/Makefile b/drivers/net/fm10k/Makefile index a4a8f56..06ebf83 100644 --- a/drivers/net/fm10k/Makefile +++ b/drivers/net/fm10k/Makefile @@ -93,6 +93,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_common.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_mbx.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_vf.c SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_api.c +SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_rxtx_vec.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += lib/librte_eal lib/librte_ether diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c new file mode 100644 index 000..69174d9 --- /dev/null +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -0,0 +1,45 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2013-2015 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 + +#include +#include +#include "fm10k.h" +#include "base/fm10k_type.h" + +#include + +#ifndef __INTEL_COMPILER +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif -- 1.7.7.6
[dpdk-dev] [PATCH v2 03/16] fm10k: Add a new func to initialize all parameters
From: "Chen Jing D(Mark)" Add new function fm10k_params_init to initialize all fm10k related variables. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k_ethdev.c | 34 ++ 1 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 3c7784e..1bc1e7c 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -2066,6 +2066,26 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = { .rss_hash_conf_get = fm10k_rss_hash_conf_get, }; +static void +fm10k_params_init(struct rte_eth_dev *dev) +{ + struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct fm10k_dev_info *info = FM10K_DEV_PRIVATE_TO_INFO(dev); + /* Inialize bus info. Normally we would call fm10k_get_bus_info(), but +* there is no way to get link status without reading BAR4. Until this +* works, assume we have maximum bandwidth. +* @todo - fix bus info +*/ + hw->bus_caps.speed = fm10k_bus_speed_8000; + hw->bus_caps.width = fm10k_bus_width_pcie_x8; + hw->bus_caps.payload = fm10k_bus_payload_512; + hw->bus.speed = fm10k_bus_speed_8000; + hw->bus.width = fm10k_bus_width_pcie_x8; + hw->bus.payload = fm10k_bus_payload_256; + + info->rx_vec_allowed = true; +} + static int eth_fm10k_dev_init(struct rte_eth_dev *dev) { @@ -2112,18 +2132,8 @@ eth_fm10k_dev_init(struct rte_eth_dev *dev) return -EIO; } - /* -* Inialize bus info. Normally we would call fm10k_get_bus_info(), but -* there is no way to get link status without reading BAR4. Until this -* works, assume we have maximum bandwidth. -* @todo - fix bus info -*/ - hw->bus_caps.speed = fm10k_bus_speed_8000; - hw->bus_caps.width = fm10k_bus_width_pcie_x8; - hw->bus_caps.payload = fm10k_bus_payload_512; - hw->bus.speed = fm10k_bus_speed_8000; - hw->bus.width = fm10k_bus_width_pcie_x8; - hw->bus.payload = fm10k_bus_payload_256; + /* Initialize parameters */ + fm10k_params_init(dev); /* Initialize the hw */ diag = fm10k_init_hw(hw); -- 1.7.7.6
[dpdk-dev] [PATCH v2 05/16] fm10k: add 2 functions to parse pkt_type and offload flag
From: "Chen Jing D(Mark)" Add 2 functions, in which using SSE instructions to parse RX desc to get pkt_type and ol_flags in mbuf. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k_rxtx_vec.c | 127 1 files changed, 127 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 75533f9..581a309 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -44,6 +44,133 @@ #pragma GCC diagnostic ignored "-Wcast-qual" #endif +/* Handling the offload flags (olflags) field takes computation + * time when receiving packets. Therefore we provide a flag to disable + * the processing of the olflags field when they are not needed. This + * gives improved performance, at the cost of losing the offload info + * in the received packet + */ +#ifdef RTE_LIBRTE_FM10K_RX_OLFLAGS_ENABLE + +/* Vlan present flag shift */ +#define VP_SHIFT (2) +/* L3 type shift */ +#define L3TYPE_SHIFT (4) +/* L4 type shift */ +#define L4TYPE_SHIFT (7) + +static inline void +fm10k_desc_to_olflags_v(__m128i descs[4], struct rte_mbuf **rx_pkts) +{ + __m128i ptype0, ptype1, vtag0, vtag1; + union { + uint16_t e[4]; + uint64_t dword; + } vol; + + const __m128i pkttype_msk = _mm_set_epi16( + 0x, 0x, 0x, 0x, + PKT_RX_VLAN_PKT, PKT_RX_VLAN_PKT, + PKT_RX_VLAN_PKT, PKT_RX_VLAN_PKT); + + /* mask everything except rss type */ + const __m128i rsstype_msk = _mm_set_epi16( + 0x, 0x, 0x, 0x, + 0x000F, 0x000F, 0x000F, 0x000F); + + /* map rss type to rss hash flag */ + const __m128i rss_flags = _mm_set_epi8(0, 0, 0, 0, + 0, 0, 0, PKT_RX_RSS_HASH, + PKT_RX_RSS_HASH, 0, PKT_RX_RSS_HASH, 0, + PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, PKT_RX_RSS_HASH, 0); + + ptype0 = _mm_unpacklo_epi16(descs[0], descs[1]); + ptype1 = _mm_unpacklo_epi16(descs[2], descs[3]); + vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]); + vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]); + + ptype0 = _mm_unpacklo_epi32(ptype0, ptype1); + ptype0 = _mm_and_si128(ptype0, rsstype_msk); + ptype0 = _mm_shuffle_epi8(rss_flags, ptype0); + + vtag1 = _mm_unpacklo_epi32(vtag0, vtag1); + vtag1 = _mm_srli_epi16(vtag1, VP_SHIFT); + vtag1 = _mm_and_si128(vtag1, pkttype_msk); + + vtag1 = _mm_or_si128(ptype0, vtag1); + vol.dword = _mm_cvtsi128_si64(vtag1); + + rx_pkts[0]->ol_flags = vol.e[0]; + rx_pkts[1]->ol_flags = vol.e[1]; + rx_pkts[2]->ol_flags = vol.e[2]; + rx_pkts[3]->ol_flags = vol.e[3]; +} + +static inline void +fm10k_desc_to_pktype_v(__m128i descs[4], struct rte_mbuf **rx_pkts) +{ + __m128i l3l4type0, l3l4type1, l3type, l4type; + union { + uint16_t e[4]; + uint64_t dword; + } vol; + + /* L3 pkt type mask Bit4 to Bit6 */ + const __m128i l3type_msk = _mm_set_epi16( + 0x, 0x, 0x, 0x, + 0x0070, 0x0070, 0x0070, 0x0070); + + /* L4 pkt type mask Bit7 to Bit9 */ + const __m128i l4type_msk = _mm_set_epi16( + 0x, 0x, 0x, 0x, + 0x0380, 0x0380, 0x0380, 0x0380); + + /* convert RRC l3 type to mbuf format */ + const __m128i l3type_flags = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, RTE_PTYPE_L3_IPV6_EXT, + RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV4_EXT, + RTE_PTYPE_L3_IPV4, 0); + + /* Convert RRC l4 type to mbuf format l4type_flags shift-left 8 bits +* to fill into8 bits length. +*/ + const __m128i l4type_flags = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, + RTE_PTYPE_TUNNEL_GENEVE >> 8, + RTE_PTYPE_TUNNEL_NVGRE >> 8, + RTE_PTYPE_TUNNEL_VXLAN >> 8, + RTE_PTYPE_TUNNEL_GRE >> 8, + RTE_PTYPE_L4_UDP >> 8, + RTE_PTYPE_L4_TCP >> 8, + 0); + + l3l4type0 = _mm_unpacklo_epi16(descs[0], descs[1]); + l3l4type1 = _mm_unpacklo_epi16(descs[2], descs[3]); + l3l4type0 = _mm_unpacklo_epi32(l3l4type0, l3l4type1); + + l3type = _mm_and_si128(l3l4type0, l3type_msk); + l4type = _mm_and_si128(l3l4type0, l4type_msk); + + l3type = _mm_srli_epi16(l3type, L3TYPE_SHIFT); + l4type = _mm_srli_epi16(l4type, L4TYPE_SHIFT); + + l3type = _mm_shuffle_epi8(l3type_flags, l3type); + /* l4type_flags shift-left for 8 bits, need shift-right back */ + l4type = _mm_shuffle_epi8(l4type_flags, l4type); + + l4type = _mm_slli_epi16(l4type,
[dpdk-dev] [PATCH v2 06/16] fm10k: add Vector RX function
From: "Chen Jing D(Mark)" Add func fm10k_recv_raw_pkts_vec to parse raw packets, in which includes possible chained packets. Add func fm10k_recv_pkts_vec to receive single mbuf packet. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h |1 + drivers/net/fm10k/fm10k_rxtx_vec.c | 196 2 files changed, 197 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 5df7960..f04ba2c 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -327,4 +327,5 @@ uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq); +uint16_t fm10k_recv_pkts_vec(void *, struct rte_mbuf **, uint16_t); #endif diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 581a309..482b76c 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -281,3 +281,199 @@ fm10k_rxq_rearm(struct fm10k_rx_queue *rxq) /* Update the tail pointer on the NIC */ FM10K_PCI_REG_WRITE(rxq->tail_ptr, rx_id); } + +static inline uint16_t +fm10k_recv_raw_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts, uint8_t *split_packet) +{ + volatile union fm10k_rx_desc *rxdp; + struct rte_mbuf **mbufp; + uint16_t nb_pkts_recd; + int pos; + struct fm10k_rx_queue *rxq = rx_queue; + uint64_t var; + __m128i shuf_msk; + __m128i dd_check, eop_check; + uint16_t next_dd; + + next_dd = rxq->next_dd; + + /* Just the act of getting into the function from the application is +* going to cost about 7 cycles +*/ + rxdp = rxq->hw_ring + next_dd; + + _mm_prefetch((const void *)rxdp, _MM_HINT_T0); + + /* See if we need to rearm the RX queue - gives the prefetch a bit +* of time to act +*/ + if (rxq->rxrearm_nb > RTE_FM10K_RXQ_REARM_THRESH) + fm10k_rxq_rearm(rxq); + + /* Before we start moving massive data around, check to see if +* there is actually a packet available +*/ + if (!(rxdp->d.staterr & FM10K_RXD_STATUS_DD)) + return 0; + + /* 4 packets DD mask */ + dd_check = _mm_set_epi64x(0x00010001LL, 0x00010001LL); + + /* 4 packets EOP mask */ + eop_check = _mm_set_epi64x(0x00020002LL, 0x00020002LL); + + /* mask to shuffle from desc. to mbuf */ + shuf_msk = _mm_set_epi8( + 7, 6, 5, 4, /* octet 4~7, 32bits rss */ + 15, 14, /* octet 14~15, low 16 bits vlan_macip */ + 13, 12, /* octet 12~13, 16 bits data_len */ + 0xFF, 0xFF, /* skip high 16 bits pkt_len, zero out */ + 13, 12, /* octet 12~13, low 16 bits pkt_len */ + 0xFF, 0xFF, /* skip high 16 bits pkt_type */ + 0xFF, 0xFF /* Skip pkt_type field in shuffle operation */ + ); + + /* Cache is empty -> need to scan the buffer rings, but first move +* the next 'n' mbufs into the cache +*/ + mbufp = &rxq->sw_ring[next_dd]; + + /* A. load 4 packet in one loop +* [A*. mask out 4 unused dirty field in desc] +* B. copy 4 mbuf point from swring to rx_pkts +* C. calc the number of DD bits among the 4 packets +* [C*. extract the end-of-packet bit, if requested] +* D. fill info. from desc to mbuf +*/ + for (pos = 0, nb_pkts_recd = 0; pos < nb_pkts; + pos += RTE_FM10K_DESCS_PER_LOOP, + rxdp += RTE_FM10K_DESCS_PER_LOOP) { + __m128i descs0[RTE_FM10K_DESCS_PER_LOOP]; + __m128i pkt_mb1, pkt_mb2, pkt_mb3, pkt_mb4; + __m128i zero, staterr, sterr_tmp1, sterr_tmp2; + __m128i mbp1, mbp2; /* two mbuf pointer in one XMM reg. */ + + /* B.1 load 1 mbuf point */ + mbp1 = _mm_loadu_si128((__m128i *)&mbufp[pos]); + + /* Read desc statuses backwards to avoid race condition */ + /* A.1 load 4 pkts desc */ + descs0[3] = _mm_loadu_si128((__m128i *)(rxdp + 3)); + + /* B.2 copy 2 mbuf point into rx_pkts */ + _mm_storeu_si128((__m128i *)&rx_pkts[pos], mbp1); + + /* B.1 load 1 mbuf point */ + mbp2 = _mm_loadu_si128((__m128i *)&mbufp[pos+2]); + + descs0[2] = _mm_loadu_si128((__m128i *)(rxdp + 2)); + /* B.1 load 2 mbuf point */ + descs0[1] = _mm_loadu_si128((__m128i *)(rxdp + 1)); + descs0[0] = _mm_loadu_si128((__m128i *)(rxdp)); + + /* B.2 copy 2 mbuf point into rx_pkts */ + _mm_storeu_si128((__m128i *)&rx_pkts[pos+2], mbp2); + + /* avoid compiler reorder optimizatio
[dpdk-dev] [PATCH v2 07/16] fm10k: add func to do Vector RX condition check
From: "Chen Jing D(Mark)" Add func fm10k_rx_vec_condition_check to check if Vector RX func can be applied. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h |1 + drivers/net/fm10k/fm10k_rxtx_vec.c | 31 +++ 2 files changed, 32 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index f04ba2c..1502ae3 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -327,5 +327,6 @@ uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq); +int fm10k_rx_vec_condition_check(struct rte_eth_dev *); uint16_t fm10k_recv_pkts_vec(void *, struct rte_mbuf **, uint16_t); #endif diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 482b76c..96ca28b 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -172,6 +172,37 @@ fm10k_desc_to_pktype_v(__m128i descs[4], struct rte_mbuf **rx_pkts) #endif int __attribute__((cold)) +fm10k_rx_vec_condition_check(struct rte_eth_dev *dev) +{ +#ifndef RTE_LIBRTE_IEEE1588 + struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; + struct rte_fdir_conf *fconf = &dev->data->dev_conf.fdir_conf; + +#ifndef RTE_FM10K_RX_OLFLAGS_ENABLE + /* whithout rx ol_flags, no VP flag report */ + if (rxmode->hw_vlan_extend != 0) + return -1; +#endif + + /* no fdir support */ + if (fconf->mode != RTE_FDIR_MODE_NONE) + return -1; + + /* - no csum error report support +* - no header split support +*/ + if (rxmode->hw_ip_checksum == 1 || + rxmode->header_split == 1) + return -1; + + return 0; +#else + RTE_SET_USED(dev); + return -1; +#endif +} + +int __attribute__((cold)) fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq) { uintptr_t p; -- 1.7.7.6
[dpdk-dev] [PATCH v2 08/16] fm10k: add Vector RX scatter function
From: "Chen Jing D(Mark)" Add func fm10k_recv_scattered_pkts_vec to receive chained packets with SSE instructions. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h |2 + drivers/net/fm10k/fm10k_rxtx_vec.c | 88 2 files changed, 90 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 1502ae3..06697fa 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -329,4 +329,6 @@ uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, int fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq); int fm10k_rx_vec_condition_check(struct rte_eth_dev *); uint16_t fm10k_recv_pkts_vec(void *, struct rte_mbuf **, uint16_t); +uint16_t fm10k_recv_scattered_pkts_vec(void *, struct rte_mbuf **, + uint16_t); #endif diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 96ca28b..237de9d 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -508,3 +508,91 @@ fm10k_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, { return fm10k_recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL); } + +static inline uint16_t +fm10k_reassemble_packets(struct fm10k_rx_queue *rxq, + struct rte_mbuf **rx_bufs, + uint16_t nb_bufs, uint8_t *split_flags) +{ + struct rte_mbuf *pkts[RTE_FM10K_MAX_RX_BURST]; /*finished pkts*/ + struct rte_mbuf *start = rxq->pkt_first_seg; + struct rte_mbuf *end = rxq->pkt_last_seg; + unsigned pkt_idx, buf_idx; + + + for (buf_idx = 0, pkt_idx = 0; buf_idx < nb_bufs; buf_idx++) { + if (end != NULL) { + /* processing a split packet */ + end->next = rx_bufs[buf_idx]; + start->nb_segs++; + start->pkt_len += rx_bufs[buf_idx]->data_len; + end = end->next; + + if (!split_flags[buf_idx]) { + /* it's the last packet of the set */ + start->hash = end->hash; + start->ol_flags = end->ol_flags; + pkts[pkt_idx++] = start; + start = end = NULL; + } + } else { + /* not processing a split packet */ + if (!split_flags[buf_idx]) { + /* not a split packet, save and skip */ + pkts[pkt_idx++] = rx_bufs[buf_idx]; + continue; + } + end = start = rx_bufs[buf_idx]; + } + } + + /* save the partial packet for next time */ + rxq->pkt_first_seg = start; + rxq->pkt_last_seg = end; + memcpy(rx_bufs, pkts, pkt_idx * (sizeof(*pkts))); + return pkt_idx; +} + +/* + * vPMD receive routine that reassembles scattered packets + * + * Notice: + * - don't support ol_flags for rss and csum err + * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet + * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST + * numbers of DD bit + * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two + */ +uint16_t +fm10k_recv_scattered_pkts_vec(void *rx_queue, + struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + struct fm10k_rx_queue *rxq = rx_queue; + uint8_t split_flags[RTE_FM10K_MAX_RX_BURST] = {0}; + unsigned i = 0; + + /* get some new buffers */ + uint16_t nb_bufs = fm10k_recv_raw_pkts_vec(rxq, rx_pkts, nb_pkts, + split_flags); + if (nb_bufs == 0) + return 0; + + /* happy day case, full burst + no packets to be joined */ + const uint64_t *split_fl64 = (uint64_t *)split_flags; + if (rxq->pkt_first_seg == NULL && + split_fl64[0] == 0 && split_fl64[1] == 0 && + split_fl64[2] == 0 && split_fl64[3] == 0) + return nb_bufs; + + /* reassemble any packets that need reassembly*/ + if (rxq->pkt_first_seg == NULL) { + /* find the first split flag, and only reassemble then*/ + while (i < nb_bufs && !split_flags[i]) + i++; + if (i == nb_bufs) + return nb_bufs; + } + return i + fm10k_reassemble_packets(rxq, &rx_pkts[i], nb_bufs - i, + &split_flags[i]); +} -- 1.7.7.6
[dpdk-dev] [PATCH v2 00/16] Vector Rx/Tx PMD implementation for fm10k
From: "Chen Jing D(Mark)" v2: - Fix a typo issue - Fix an improper prefetch in vector RX function, in which prefetches un-initialized mbuf. - Remove limitation on number of desc pointer in vector RX function. - Re-organize some comments. - Add a new patch to fix a crash issue in vector RX func. - Add a new patch to update release notes. v1: This patch set includes Vector Rx/Tx functions to receive/transmit packets for fm10k devices. It also contains logic to do sanity check for proper RX/TX function selections. Chen Jing D(Mark) (16): fm10k: add new vPMD file fm10k: add vPMD pre-condition check for each RX queue fm10k: Add a new func to initialize all parameters fm10k: add func to re-allocate mbuf for RX ring fm10k: add 2 functions to parse pkt_type and offload flag fm10k: add Vector RX function fm10k: add func to do Vector RX condition check fm10k: add Vector RX scatter function fm10k: add function to decide best RX function fm10k: add func to release mbuf in case Vector RX applied fm10k: add Vector TX function fm10k: use func pointer to reset TX queue and mbuf release fm10k: introduce 2 funcs to reset TX queue and mbuf release fm10k: Add function to decide best TX func fm10k: fix a crash issue in vector RX func doc: release notes update for fm10k Vector PMD doc/guides/rel_notes/release_2_2.rst |5 + drivers/net/fm10k/Makefile |1 + drivers/net/fm10k/fm10k.h| 45 ++- drivers/net/fm10k/fm10k_ethdev.c | 168 ++- drivers/net/fm10k/fm10k_rxtx_vec.c | 834 ++ 5 files changed, 1025 insertions(+), 28 deletions(-) create mode 100644 drivers/net/fm10k/fm10k_rxtx_vec.c -- 1.7.7.6
[dpdk-dev] [PATCH v2 10/16] fm10k: add func to release mbuf in case Vector RX applied
From: "Chen Jing D(Mark)" Since Vector RX use different variables to trace RX HW ring, it leads to need different func to release mbuf properly. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h |1 + drivers/net/fm10k/fm10k_ethdev.c |6 ++ drivers/net/fm10k/fm10k_rxtx_vec.c | 18 ++ 3 files changed, 25 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 8614e81..c5e66e2 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -329,6 +329,7 @@ uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, int fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq); int fm10k_rx_vec_condition_check(struct rte_eth_dev *); +void fm10k_rx_queue_release_mbufs_vec(struct fm10k_rx_queue *rxq); uint16_t fm10k_recv_pkts_vec(void *, struct rte_mbuf **, uint16_t); uint16_t fm10k_recv_scattered_pkts_vec(void *, struct rte_mbuf **, uint16_t); diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 53c4ef1..2c3d8be 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -143,6 +143,12 @@ rx_queue_clean(struct fm10k_rx_queue *q) for (i = 0; i < q->nb_desc; ++i) q->hw_ring[i] = zero; + /* vPMD driver has a different way of releasing mbufs. */ + if (q->rx_using_sse) { + fm10k_rx_queue_release_mbufs_vec(q); + return; + } + /* free software buffers */ for (i = 0; i < q->nb_desc; ++i) { if (q->sw_ring[i]) { diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 237de9d..ab0218e 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -313,6 +313,24 @@ fm10k_rxq_rearm(struct fm10k_rx_queue *rxq) FM10K_PCI_REG_WRITE(rxq->tail_ptr, rx_id); } +void __attribute__((cold)) +fm10k_rx_queue_release_mbufs_vec(struct fm10k_rx_queue *rxq) +{ + const unsigned mask = rxq->nb_desc - 1; + unsigned i; + + if (rxq->sw_ring == NULL || rxq->rxrearm_nb >= rxq->nb_desc) + return; + + /* free all mbufs that are valid in the ring */ + for (i = rxq->next_dd; i != rxq->rxrearm_start; i = (i + 1) & mask) + rte_pktmbuf_free_seg(rxq->sw_ring[i]); + rxq->rxrearm_nb = rxq->nb_desc; + + /* set all entries to NULL */ + memset(rxq->sw_ring, 0, sizeof(rxq->sw_ring[0]) * rxq->nb_desc); +} + static inline uint16_t fm10k_recv_raw_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts, uint8_t *split_packet) -- 1.7.7.6
[dpdk-dev] [PATCH v2 02/16] fm10k: add vPMD pre-condition check for each RX queue
From: "Chen Jing D(Mark)" Add condition check in rx_queue_setup func. If number of RX desc can't satisfy vPMD requirement, record it into a variable. Or call fm10k_rxq_vec_setup to initialize Vector RX. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h | 11 --- drivers/net/fm10k/fm10k_ethdev.c | 11 +++ drivers/net/fm10k/fm10k_rxtx_vec.c | 21 + 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index c089882..362a2d0 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -135,6 +135,8 @@ struct fm10k_dev_info { /* Protect the mailbox to avoid race condition */ rte_spinlock_tmbx_lock; struct fm10k_macvlan_filter_infomacvlan; + /* Flag to indicate if RX vector conditions satisfied */ + bool rx_vec_allowed; }; /* @@ -165,9 +167,10 @@ struct fm10k_rx_queue { struct rte_mempool *mp; struct rte_mbuf **sw_ring; volatile union fm10k_rx_desc *hw_ring; - struct rte_mbuf *pkt_first_seg; /**< First segment of current packet. */ - struct rte_mbuf *pkt_last_seg; /**< Last segment of current packet. */ + struct rte_mbuf *pkt_first_seg; /* First segment of current packet. */ + struct rte_mbuf *pkt_last_seg; /* Last segment of current packet. */ uint64_t hw_ring_phys_addr; + uint64_t mbuf_initializer; /* value to init mbufs */ uint16_t next_dd; uint16_t next_alloc; uint16_t next_trigger; @@ -177,7 +180,7 @@ struct fm10k_rx_queue { uint16_t queue_id; uint8_t port_id; uint8_t drop_en; - uint8_t rx_deferred_start; /**< don't start this queue in dev start. */ + uint8_t rx_deferred_start; /* don't start this queue in dev start. */ }; /* @@ -313,4 +316,6 @@ uint16_t fm10k_recv_scattered_pkts(void *rx_queue, uint16_t fm10k_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); + +int fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq); #endif diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index a69c990..3c7784e 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -1251,6 +1251,7 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, const struct rte_eth_rxconf *conf, struct rte_mempool *mp) { struct fm10k_hw *hw = FM10K_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct fm10k_dev_info *dev_info = FM10K_DEV_PRIVATE_TO_INFO(dev); struct fm10k_rx_queue *q; const struct rte_memzone *mz; @@ -1333,6 +1334,16 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, q->hw_ring_phys_addr = mz->phys_addr; #endif + /* Check if number of descs satisfied Vector requirement */ + if (!rte_is_power_of_2(nb_desc)) { + PMD_INIT_LOG(DEBUG, "queue[%d] doesn't meet Vector Rx " + "preconditions - canceling the feature for " + "the whole port[%d]", +q->queue_id, q->port_id); + dev_info->rx_vec_allowed = false; + } else + fm10k_rxq_vec_setup(q); + dev->data->rx_queues[queue_id] = q; return 0; } diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 69174d9..34b677b 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -43,3 +43,24 @@ #ifndef __INTEL_COMPILER #pragma GCC diagnostic ignored "-Wcast-qual" #endif + +int __attribute__((cold)) +fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq) +{ + uintptr_t p; + struct rte_mbuf mb_def = { .buf_addr = 0 }; /* zeroed mbuf */ + + mb_def.nb_segs = 1; + /* data_off will be ajusted after new mbuf allocated for 512-byte +* alignment. +*/ + mb_def.data_off = RTE_PKTMBUF_HEADROOM; + mb_def.port = rxq->port_id; + rte_mbuf_refcnt_set(&mb_def, 1); + + /* prevent compiler reordering: rearm_data covers previous fields */ + rte_compiler_barrier(); + p = (uintptr_t)&mb_def.rearm_data; + rxq->mbuf_initializer = *(uint64_t *)p; + return 0; +} -- 1.7.7.6
[dpdk-dev] [PATCH v2 04/16] fm10k: add func to re-allocate mbuf for RX ring
From: "Chen Jing D(Mark)" Add function fm10k_rxq_rearm to re-allocate mbuf for used desc in RX HW ring. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h |9 drivers/net/fm10k/fm10k_ethdev.c |3 + drivers/net/fm10k/fm10k_rxtx_vec.c | 90 3 files changed, 102 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 362a2d0..5df7960 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -123,6 +123,12 @@ #define FM10K_VFTA_BIT(vlan_id)(1 << ((vlan_id) & 0x1F)) #define FM10K_VFTA_IDX(vlan_id)((vlan_id) >> 5) +#define RTE_FM10K_RXQ_REARM_THRESH 32 +#define RTE_FM10K_VPMD_TX_BURST 32 +#define RTE_FM10K_MAX_RX_BURST RTE_FM10K_RXQ_REARM_THRESH +#define RTE_FM10K_TX_MAX_FREE_BUF_SZ64 +#define RTE_FM10K_DESCS_PER_LOOP4 + struct fm10k_macvlan_filter_info { uint16_t vlan_num; /* Total VLAN number */ uint16_t mac_num;/* Total mac number */ @@ -178,6 +184,9 @@ struct fm10k_rx_queue { volatile uint32_t *tail_ptr; uint16_t nb_desc; uint16_t queue_id; + /* Below 2 fields only valid in case vPMD is applied. */ + uint16_t rxrearm_nb; /* number of remaining to be re-armed */ + uint16_t rxrearm_start; /* the idx we start the re-arming from */ uint8_t port_id; uint8_t drop_en; uint8_t rx_deferred_start; /* don't start this queue in dev start. */ diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 1bc1e7c..24f936a 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -121,6 +121,9 @@ rx_queue_reset(struct fm10k_rx_queue *q) q->next_alloc = 0; q->next_trigger = q->alloc_thresh - 1; FM10K_PCI_REG_WRITE(q->tail_ptr, q->nb_desc - 1); + q->rxrearm_start = 0; + q->rxrearm_nb = 0; + return 0; } diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index 34b677b..75533f9 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -64,3 +64,93 @@ fm10k_rxq_vec_setup(struct fm10k_rx_queue *rxq) rxq->mbuf_initializer = *(uint64_t *)p; return 0; } + +static inline void +fm10k_rxq_rearm(struct fm10k_rx_queue *rxq) +{ + int i; + uint16_t rx_id; + volatile union fm10k_rx_desc *rxdp; + struct rte_mbuf **mb_alloc = &rxq->sw_ring[rxq->rxrearm_start]; + struct rte_mbuf *mb0, *mb1; + __m128i head_off = _mm_set_epi64x( + RTE_PKTMBUF_HEADROOM + FM10K_RX_DATABUF_ALIGN - 1, + RTE_PKTMBUF_HEADROOM + FM10K_RX_DATABUF_ALIGN - 1); + __m128i dma_addr0, dma_addr1; + /* Rx buffer need to be aligned with 512 byte */ + const __m128i hba_msk = _mm_set_epi64x(0, + UINT64_MAX - FM10K_RX_DATABUF_ALIGN + 1); + + rxdp = rxq->hw_ring + rxq->rxrearm_start; + + /* Pull 'n' more MBUFs into the software ring */ + if (rte_mempool_get_bulk(rxq->mp, +(void *)mb_alloc, +RTE_FM10K_RXQ_REARM_THRESH) < 0) { + rte_eth_devices[rxq->port_id].data->rx_mbuf_alloc_failed += + RTE_FM10K_RXQ_REARM_THRESH; + return; + } + + /* Initialize the mbufs in vector, process 2 mbufs in one loop */ + for (i = 0; i < RTE_FM10K_RXQ_REARM_THRESH; i += 2, mb_alloc += 2) { + __m128i vaddr0, vaddr1; + uintptr_t p0, p1; + + mb0 = mb_alloc[0]; + mb1 = mb_alloc[1]; + + /* Flush mbuf with pkt template. +* Data to be rearmed is 6 bytes long. +* Though, RX will overwrite ol_flags that are coming next +* anyway. So overwrite whole 8 bytes with one load: +* 6 bytes of rearm_data plus first 2 bytes of ol_flags. +*/ + p0 = (uintptr_t)&mb0->rearm_data; + *(uint64_t *)p0 = rxq->mbuf_initializer; + p1 = (uintptr_t)&mb1->rearm_data; + *(uint64_t *)p1 = rxq->mbuf_initializer; + + /* load buf_addr(lo 64bit) and buf_physaddr(hi 64bit) */ + vaddr0 = _mm_loadu_si128((__m128i *)&(mb0->buf_addr)); + vaddr1 = _mm_loadu_si128((__m128i *)&(mb1->buf_addr)); + + /* convert pa to dma_addr hdr/data */ + dma_addr0 = _mm_unpackhi_epi64(vaddr0, vaddr0); + dma_addr1 = _mm_unpackhi_epi64(vaddr1, vaddr1); + + /* add headroom to pa values */ + dma_addr0 = _mm_add_epi64(dma_addr0, head_off); + dma_addr1 = _mm_add_epi64(dma_addr1, head_off); + + /* Do 512 byte alignment to satisfy HW requirement, in the +* meanwhile, set Header Buffer
[dpdk-dev] [PATCH v2 12/16] fm10k: use func pointer to reset TX queue and mbuf release
From: "Chen Jing D(Mark)" Vector TX use different way to manage TX queue, it's necessary to use different functions to reset TX queue and release mbuf in TX queue. So, introduce 2 function pointers to do such ops. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h|9 + drivers/net/fm10k/fm10k_ethdev.c | 21 - 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 0a4c174..2bead12 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -204,11 +204,14 @@ struct fifo { uint16_t *endp; }; +struct fm10k_txq_ops; + struct fm10k_tx_queue { struct rte_mbuf **sw_ring; struct fm10k_tx_desc *hw_ring; uint64_t hw_ring_phys_addr; struct fifo rs_tracker; + const struct fm10k_txq_ops *ops; /* txq ops */ uint16_t last_free; uint16_t next_free; uint16_t nb_free; @@ -225,6 +228,11 @@ struct fm10k_tx_queue { uint16_t queue_id; }; +struct fm10k_txq_ops { + void (*release_mbufs)(struct fm10k_tx_queue *txq); + void (*reset)(struct fm10k_tx_queue *txq); +}; + #define MBUF_DMA_ADDR(mb) \ ((uint64_t) ((mb)->buf_physaddr + (mb)->data_off)) @@ -338,4 +346,5 @@ uint16_t fm10k_recv_scattered_pkts_vec(void *, struct rte_mbuf **, uint16_t); uint16_t fm10k_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); +void fm10k_txq_vec_setup(struct fm10k_tx_queue *txq); #endif diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 2c3d8be..0a523eb 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -292,6 +292,11 @@ tx_queue_disable(struct fm10k_hw *hw, uint16_t qnum) return 0; } +static const struct fm10k_txq_ops def_txq_ops = { + .release_mbufs = tx_queue_free, + .reset = tx_queue_reset, +}; + static int fm10k_dev_configure(struct rte_eth_dev *dev) { @@ -571,7 +576,8 @@ fm10k_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id) PMD_INIT_FUNC_TRACE(); if (tx_queue_id < dev->data->nb_tx_queues) { - tx_queue_reset(dev->data->tx_queues[tx_queue_id]); + struct fm10k_tx_queue *q = dev->data->tx_queues[tx_queue_id]; + q->ops->reset(q); /* reset head and tail pointers */ FM10K_WRITE_REG(hw, FM10K_TDH(tx_queue_id), 0); @@ -837,8 +843,10 @@ fm10k_dev_queue_release(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); if (dev->data->tx_queues) { - for (i = 0; i < dev->data->nb_tx_queues; i++) - fm10k_tx_queue_release(dev->data->tx_queues[i]); + for (i = 0; i < dev->data->nb_tx_queues; i++) { + struct fm10k_tx_queue *txq = dev->data->tx_queues[i]; + txq->ops->release_mbufs(txq); + } } if (dev->data->rx_queues) { @@ -1454,7 +1462,8 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, * different socket than was previously used. */ if (dev->data->tx_queues[queue_id] != NULL) { - tx_queue_free(dev->data->tx_queues[queue_id]); + struct fm10k_tx_queue *txq = dev->data->tx_queues[queue_id]; + txq->ops->release_mbufs(txq); dev->data->tx_queues[queue_id] = NULL; } @@ -1470,6 +1479,7 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, q->nb_desc = nb_desc; q->port_id = dev->data->port_id; q->queue_id = queue_id; + q->ops = &def_txq_ops; q->tail_ptr = (volatile uint32_t *) &((uint32_t *)hw->hw_addr)[FM10K_TDT(queue_id)]; if (handle_txconf(q, conf)) @@ -1528,9 +1538,10 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, static void fm10k_tx_queue_release(void *queue) { + struct fm10k_tx_queue *q = queue; PMD_INIT_FUNC_TRACE(); - tx_queue_free(queue); + q->ops->release_mbufs(q); } static int -- 1.7.7.6
[dpdk-dev] [PATCH v2 09/16] fm10k: add function to decide best RX function
From: "Chen Jing D(Mark)" Add func fm10k_set_rx_function to decide best RX func in fm10k_dev_rx_init Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h|1 + drivers/net/fm10k/fm10k_ethdev.c | 36 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 06697fa..8614e81 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -187,6 +187,7 @@ struct fm10k_rx_queue { /* Below 2 fields only valid in case vPMD is applied. */ uint16_t rxrearm_nb; /* number of remaining to be re-armed */ uint16_t rxrearm_start; /* the idx we start the re-arming from */ + uint16_t rx_using_sse; /* indicates that vector RX is in use */ uint8_t port_id; uint8_t drop_en; uint8_t rx_deferred_start; /* don't start this queue in dev start. */ diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 24f936a..53c4ef1 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -67,6 +67,7 @@ static void fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev); static void fm10k_tx_queue_release(void *queue); static void fm10k_rx_queue_release(void *queue); +static void fm10k_set_rx_function(struct rte_eth_dev *dev); static void fm10k_mbx_initlock(struct fm10k_hw *hw) @@ -462,7 +463,6 @@ fm10k_dev_rx_init(struct rte_eth_dev *dev) dev->data->dev_conf.rxmode.enable_scatter) { uint32_t reg; dev->data->scattered_rx = 1; - dev->rx_pkt_burst = fm10k_recv_scattered_pkts; reg = FM10K_READ_REG(hw, FM10K_SRRCTL(i)); reg |= FM10K_SRRCTL_BUFFER_CHAINING_EN; FM10K_WRITE_REG(hw, FM10K_SRRCTL(i), reg); @@ -478,6 +478,9 @@ fm10k_dev_rx_init(struct rte_eth_dev *dev) /* Configure RSS if applicable */ fm10k_dev_mq_rx_configure(dev); + + /* Decide the best RX function */ + fm10k_set_rx_function(dev); return 0; } @@ -2069,6 +2072,34 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = { .rss_hash_conf_get = fm10k_rss_hash_conf_get, }; +static void __attribute__((cold)) +fm10k_set_rx_function(struct rte_eth_dev *dev) +{ + struct fm10k_dev_info *dev_info = FM10K_DEV_PRIVATE_TO_INFO(dev); + uint16_t i, rx_using_sse; + + /* In order to allow Vector Rx there are a few configuration +* conditions to be met. +*/ + if (!fm10k_rx_vec_condition_check(dev) && dev_info->rx_vec_allowed) { + if (dev->data->scattered_rx) + dev->rx_pkt_burst = fm10k_recv_scattered_pkts_vec; + else + dev->rx_pkt_burst = fm10k_recv_pkts_vec; + } else if (dev->data->scattered_rx) + dev->rx_pkt_burst = fm10k_recv_scattered_pkts; + + rx_using_sse = + (dev->rx_pkt_burst == fm10k_recv_scattered_pkts_vec || + dev->rx_pkt_burst == fm10k_recv_pkts_vec); + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + struct fm10k_rx_queue *rxq = dev->data->rx_queues[i]; + rxq->rx_using_sse = rx_using_sse; + } + +} + static void fm10k_params_init(struct rte_eth_dev *dev) { @@ -2102,9 +2133,6 @@ eth_fm10k_dev_init(struct rte_eth_dev *dev) dev->rx_pkt_burst = &fm10k_recv_pkts; dev->tx_pkt_burst = &fm10k_xmit_pkts; - if (dev->data->scattered_rx) - dev->rx_pkt_burst = &fm10k_recv_scattered_pkts; - /* only initialize in the primary process */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; -- 1.7.7.6
[dpdk-dev] [PATCH v2 11/16] fm10k: add Vector TX function
From: "Chen Jing D(Mark)" Add Vector TX func fm10k_xmit_pkts_vec to transmit packets. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h |5 + drivers/net/fm10k/fm10k_rxtx_vec.c | 150 2 files changed, 155 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index c5e66e2..0a4c174 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -215,6 +215,9 @@ struct fm10k_tx_queue { uint16_t nb_used; uint16_t free_thresh; uint16_t rs_thresh; + /* Below 2 fields only valid in case vPMD is applied. */ + uint16_t next_rs; /* Next pos to set RS flag */ + uint16_t next_dd; /* Next pos to check DD flag */ volatile uint32_t *tail_ptr; uint16_t nb_desc; uint8_t port_id; @@ -333,4 +336,6 @@ void fm10k_rx_queue_release_mbufs_vec(struct fm10k_rx_queue *rxq); uint16_t fm10k_recv_pkts_vec(void *, struct rte_mbuf **, uint16_t); uint16_t fm10k_recv_scattered_pkts_vec(void *, struct rte_mbuf **, uint16_t); +uint16_t fm10k_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts); #endif diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index ab0218e..f119c2c 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -614,3 +614,153 @@ fm10k_recv_scattered_pkts_vec(void *rx_queue, return i + fm10k_reassemble_packets(rxq, &rx_pkts[i], nb_bufs - i, &split_flags[i]); } + +static inline void +vtx1(volatile struct fm10k_tx_desc *txdp, + struct rte_mbuf *pkt, uint64_t flags) +{ + __m128i descriptor = _mm_set_epi64x(flags << 56 | + pkt->vlan_tci << 16 | pkt->data_len, + MBUF_DMA_ADDR(pkt)); + _mm_store_si128((__m128i *)txdp, descriptor); +} + +static inline void +vtx(volatile struct fm10k_tx_desc *txdp, + struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags) +{ + int i; + + for (i = 0; i < nb_pkts; ++i, ++txdp, ++pkt) + vtx1(txdp, *pkt, flags); +} + +static inline int __attribute__((always_inline)) +fm10k_tx_free_bufs(struct fm10k_tx_queue *txq) +{ + struct rte_mbuf **txep; + uint8_t flags; + uint32_t n; + uint32_t i; + int nb_free = 0; + struct rte_mbuf *m, *free[RTE_FM10K_TX_MAX_FREE_BUF_SZ]; + + /* check DD bit on threshold descriptor */ + flags = txq->hw_ring[txq->next_dd].flags; + if (!(flags & FM10K_TXD_FLAG_DONE)) + return 0; + + n = txq->rs_thresh; + + /* First buffer to free from S/W ring is at index +* next_dd - (rs_thresh-1) +*/ + txep = &txq->sw_ring[txq->next_dd - (n - 1)]; + m = __rte_pktmbuf_prefree_seg(txep[0]); + if (likely(m != NULL)) { + free[0] = m; + nb_free = 1; + for (i = 1; i < n; i++) { + m = __rte_pktmbuf_prefree_seg(txep[i]); + if (likely(m != NULL)) { + if (likely(m->pool == free[0]->pool)) + free[nb_free++] = m; + else { + rte_mempool_put_bulk(free[0]->pool, + (void *)free, nb_free); + free[0] = m; + nb_free = 1; + } + } + } + rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); + } else { + for (i = 1; i < n; i++) { + m = __rte_pktmbuf_prefree_seg(txep[i]); + if (m != NULL) + rte_mempool_put(m->pool, m); + } + } + + /* buffers were freed, update counters */ + txq->nb_free = (uint16_t)(txq->nb_free + txq->rs_thresh); + txq->next_dd = (uint16_t)(txq->next_dd + txq->rs_thresh); + if (txq->next_dd >= txq->nb_desc) + txq->next_dd = (uint16_t)(txq->rs_thresh - 1); + + return txq->rs_thresh; +} + +static inline void __attribute__((always_inline)) +tx_backlog_entry(struct rte_mbuf **txep, +struct rte_mbuf **tx_pkts, uint16_t nb_pkts) +{ + int i; + + for (i = 0; i < (int)nb_pkts; ++i) + txep[i] = tx_pkts[i]; +} + +uint16_t +fm10k_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts) +{ + struct fm10k_tx_queue *txq = (struct fm10k_tx_queue *)tx_queue; + volatile struct fm10k_tx_desc *txdp; + struct rte_mbuf **txep; + uint16_t n, nb_commit, tx_id; + uint64_t flags = FM10K_TXD_FLAG_LAST; + uint64_t rs = FM10K_TXD_FLAG_RS | FM10
[dpdk-dev] [PATCH v2 14/16] fm10k: Add function to decide best TX func
From: "Chen Jing D(Mark)" Add func fm10k_set_tx_function to decide the best TX func in fm10k_dev_tx_init. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h|1 + drivers/net/fm10k/fm10k_ethdev.c | 38 -- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 2bead12..68ae1b8 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -222,6 +222,7 @@ struct fm10k_tx_queue { uint16_t next_rs; /* Next pos to set RS flag */ uint16_t next_dd; /* Next pos to check DD flag */ volatile uint32_t *tail_ptr; + uint32_t txq_flags; /* Holds flags for this TXq */ uint16_t nb_desc; uint8_t port_id; uint8_t tx_deferred_start; /** < don't start this queue in dev start. */ diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 0a523eb..046979d 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -53,6 +53,9 @@ #define CHARS_PER_UINT32 (sizeof(uint32_t)) #define BIT_MASK_PER_UINT32 ((1 << CHARS_PER_UINT32) - 1) +#define FM10K_SIMPLE_TX_FLAG ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ + ETH_TXQ_FLAGS_NOOFFLOADS) + static void fm10k_close_mbx_service(struct fm10k_hw *hw); static void fm10k_dev_promiscuous_enable(struct rte_eth_dev *dev); static void fm10k_dev_promiscuous_disable(struct rte_eth_dev *dev); @@ -68,6 +71,7 @@ fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev); static void fm10k_tx_queue_release(void *queue); static void fm10k_rx_queue_release(void *queue); static void fm10k_set_rx_function(struct rte_eth_dev *dev); +static void fm10k_set_tx_function(struct rte_eth_dev *dev); static void fm10k_mbx_initlock(struct fm10k_hw *hw) @@ -414,6 +418,10 @@ fm10k_dev_tx_init(struct rte_eth_dev *dev) base_addr >> (CHAR_BIT * sizeof(uint32_t))); FM10K_WRITE_REG(hw, FM10K_TDLEN(i), size); } + + /* set up vector or scalar TX function as appropriate */ + fm10k_set_tx_function(dev); + return 0; } @@ -980,8 +988,7 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev, }, .tx_free_thresh = FM10K_TX_FREE_THRESH_DEFAULT(0), .tx_rs_thresh = FM10K_TX_RS_THRESH_DEFAULT(0), - .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | - ETH_TXQ_FLAGS_NOOFFLOADS, + .txq_flags = FM10K_SIMPLE_TX_FLAG, }; } @@ -1479,6 +1486,7 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, q->nb_desc = nb_desc; q->port_id = dev->data->port_id; q->queue_id = queue_id; + q->txq_flags = conf->txq_flags; q->ops = &def_txq_ops; q->tail_ptr = (volatile uint32_t *) &((uint32_t *)hw->hw_addr)[FM10K_TDT(queue_id)]; @@ -2090,6 +2098,32 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = { }; static void __attribute__((cold)) +fm10k_set_tx_function(struct rte_eth_dev *dev) +{ + struct fm10k_tx_queue *txq; + int i; + int use_sse = 1; + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + if ((txq->txq_flags & FM10K_SIMPLE_TX_FLAG) != \ + FM10K_SIMPLE_TX_FLAG) { + use_sse = 0; + break; + } + } + + if (use_sse) { + for (i = 0; i < dev->data->nb_tx_queues; i++) { + txq = dev->data->tx_queues[i]; + fm10k_txq_vec_setup(txq); + } + dev->tx_pkt_burst = fm10k_xmit_pkts_vec; + } else + dev->tx_pkt_burst = fm10k_xmit_pkts; +} + +static void __attribute__((cold)) fm10k_set_rx_function(struct rte_eth_dev *dev) { struct fm10k_dev_info *dev_info = FM10K_DEV_PRIVATE_TO_INFO(dev); -- 1.7.7.6
[dpdk-dev] [PATCH v2 13/16] fm10k: introduce 2 funcs to reset TX queue and mbuf release
From: "Chen Jing D(Mark)" Add 2 funcs to reset TX queue and mbuf release when Vector TX applied. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k_rxtx_vec.c | 68 1 files changed, 68 insertions(+), 0 deletions(-) diff --git a/drivers/net/fm10k/fm10k_rxtx_vec.c b/drivers/net/fm10k/fm10k_rxtx_vec.c index f119c2c..5ed8653 100644 --- a/drivers/net/fm10k/fm10k_rxtx_vec.c +++ b/drivers/net/fm10k/fm10k_rxtx_vec.c @@ -44,6 +44,11 @@ #pragma GCC diagnostic ignored "-Wcast-qual" #endif +static void +fm10k_tx_queue_release_mbufs_vec(struct fm10k_tx_queue *txq); +static void +fm10k_reset_tx_queue(struct fm10k_tx_queue *txq); + /* Handling the offload flags (olflags) field takes computation * time when receiving packets. Therefore we provide a flag to disable * the processing of the olflags field when they are not needed. This @@ -615,6 +620,17 @@ fm10k_recv_scattered_pkts_vec(void *rx_queue, &split_flags[i]); } +static const struct fm10k_txq_ops vec_txq_ops = { + .release_mbufs = fm10k_tx_queue_release_mbufs_vec, + .reset = fm10k_reset_tx_queue, +}; + +void __attribute__((cold)) +fm10k_txq_vec_setup(struct fm10k_tx_queue *txq) +{ + txq->ops = &vec_txq_ops; +} + static inline void vtx1(volatile struct fm10k_tx_desc *txdp, struct rte_mbuf *pkt, uint64_t flags) @@ -764,3 +780,55 @@ fm10k_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts, return nb_pkts; } + +static void __attribute__((cold)) +fm10k_tx_queue_release_mbufs_vec(struct fm10k_tx_queue *txq) +{ + unsigned i; + const uint16_t max_desc = (uint16_t)(txq->nb_desc - 1); + + if (txq->sw_ring == NULL || txq->nb_free == max_desc) + return; + + /* release the used mbufs in sw_ring */ + for (i = txq->next_dd - (txq->rs_thresh - 1); +i != txq->next_free; +i = (i + 1) & max_desc) + rte_pktmbuf_free_seg(txq->sw_ring[i]); + + txq->nb_free = max_desc; + + /* reset tx_entry */ + for (i = 0; i < txq->nb_desc; i++) + txq->sw_ring[i] = NULL; + + rte_free(txq->sw_ring); + txq->sw_ring = NULL; +} + +static void __attribute__((cold)) +fm10k_reset_tx_queue(struct fm10k_tx_queue *txq) +{ + static const struct fm10k_tx_desc zeroed_desc = {0}; + struct rte_mbuf **txe = txq->sw_ring; + uint16_t i; + + /* Zero out HW ring memory */ + for (i = 0; i < txq->nb_desc; i++) + txq->hw_ring[i] = zeroed_desc; + + /* Initialize SW ring entries */ + for (i = 0; i < txq->nb_desc; i++) + txe[i] = NULL; + + txq->next_dd = (uint16_t)(txq->rs_thresh - 1); + txq->next_rs = (uint16_t)(txq->rs_thresh - 1); + + txq->next_free = 0; + txq->nb_used = 0; + /* Always allow 1 descriptor to be un-allocated to avoid +* a H/W race condition +*/ + txq->nb_free = (uint16_t)(txq->nb_desc - 1); + FM10K_PCI_REG_WRITE(txq->tail_ptr, 0); +} -- 1.7.7.6
[dpdk-dev] [PATCH v2 15/16] fm10k: fix a crash issue in vector RX func
From: "Chen Jing D(Mark)" Vector RX function will process 4 packets at a time. When the RX ring wrapps to the tail and the left descriptor size is not multiple of 4, SW will overwrite memory that not belongs to it and cause crash. The fix will allocate additional 4 HW/SW spaces at the tail to avoid overwrite. Signed-off-by: Chen Jing D(Mark) --- drivers/net/fm10k/fm10k.h|4 drivers/net/fm10k/fm10k_ethdev.c | 19 +-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/fm10k/fm10k.h b/drivers/net/fm10k/fm10k.h index 68ae1b8..82a548f 100644 --- a/drivers/net/fm10k/fm10k.h +++ b/drivers/net/fm10k/fm10k.h @@ -177,12 +177,16 @@ struct fm10k_rx_queue { struct rte_mbuf *pkt_last_seg; /* Last segment of current packet. */ uint64_t hw_ring_phys_addr; uint64_t mbuf_initializer; /* value to init mbufs */ + /* need to alloc dummy mbuf, for wraparound when scanning hw ring */ + struct rte_mbuf fake_mbuf; uint16_t next_dd; uint16_t next_alloc; uint16_t next_trigger; uint16_t alloc_thresh; volatile uint32_t *tail_ptr; uint16_t nb_desc; + /* Number of faked desc added at the tail for Vector RX function */ + uint16_t nb_fake_desc; uint16_t queue_id; /* Below 2 fields only valid in case vPMD is applied. */ uint16_t rxrearm_nb; /* number of remaining to be re-armed */ diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index 046979d..31c96ac 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -102,6 +102,7 @@ fm10k_mbx_unlock(struct fm10k_hw *hw) static inline int rx_queue_reset(struct fm10k_rx_queue *q) { + static const union fm10k_rx_desc zero = {{0}}; uint64_t dma_addr; int i, diag; PMD_INIT_FUNC_TRACE(); @@ -122,6 +123,15 @@ rx_queue_reset(struct fm10k_rx_queue *q) q->hw_ring[i].q.hdr_addr = dma_addr; } + /* initialize extra software ring entries. Space for these extra +* entries is always allocated. +*/ + memset(&q->fake_mbuf, 0x0, sizeof(q->fake_mbuf)); + for (i = 0; i < q->nb_fake_desc; ++i) { + q->sw_ring[q->nb_desc + i] = &q->fake_mbuf; + q->hw_ring[q->nb_desc + i] = zero; + } + q->next_dd = 0; q->next_alloc = 0; q->next_trigger = q->alloc_thresh - 1; @@ -147,6 +157,10 @@ rx_queue_clean(struct fm10k_rx_queue *q) for (i = 0; i < q->nb_desc; ++i) q->hw_ring[i] = zero; + /* zero faked descriptors */ + for (i = 0; i < q->nb_fake_desc; ++i) + q->hw_ring[q->nb_desc + i] = zero; + /* vPMD driver has a different way of releasing mbufs. */ if (q->rx_using_sse) { fm10k_rx_queue_release_mbufs_vec(q); @@ -1323,6 +1337,7 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, /* setup queue */ q->mp = mp; q->nb_desc = nb_desc; + q->nb_fake_desc = FM10K_MULT_RX_DESC; q->port_id = dev->data->port_id; q->queue_id = queue_id; q->tail_ptr = (volatile uint32_t *) @@ -1332,8 +1347,8 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id, /* allocate memory for the software ring */ q->sw_ring = rte_zmalloc_socket("fm10k sw ring", - nb_desc * sizeof(struct rte_mbuf *), - RTE_CACHE_LINE_SIZE, socket_id); + (nb_desc + q->nb_fake_desc) * sizeof(struct rte_mbuf *), + RTE_CACHE_LINE_SIZE, socket_id); if (q->sw_ring == NULL) { PMD_INIT_LOG(ERR, "Cannot allocate software ring"); rte_free(q); -- 1.7.7.6
[dpdk-dev] [PATCH v2 16/16] doc: release notes update for fm10k Vector PMD
From: "Chen Jing D(Mark)" Update 2.2 release notes, add descriptions for Vector PMD implementation in fm10k driver. Signed-off-by: Chen Jing D(Mark) --- doc/guides/rel_notes/release_2_2.rst |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index 9a70dae..44a3f74 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -39,6 +39,11 @@ Drivers Fixed issue with libvirt ``virsh destroy`` not killing the VM. +* **fm10k: Add Vector Rx/Tx implementation.** + + This patch set includes Vector Rx/Tx functions to receive/transmit packets + for fm10k devices. It also contains logic to do sanity check for proper + RX/TX function selections. Libraries ~ -- 1.7.7.6
[dpdk-dev] [RFC PATCH v3 0/2] Add VHOST PMD
The patch introduces a new PMD. This PMD is implemented as thin wrapper of librte_vhost. I've submitted below patches in former patch sets. But it seems some issues were fixed already. - [PATCH 1/3] vhost: Fix return value of GET_VRING_BASE message - [PATCH 2/3] vhost: Fix RESET_OWNER handling not to close callfd - [PATCH 3/3] vhost: Fix RESET_OWNER handling not to free virtqueue I've still seen some reasource leaks of vhost library, but in this RFC, I focused on vhost PMD. After I get agreement, I will submit a patch for the leak issue as separated patch. So please check directionality of vhost PMD. PATCH v3 changes: - Optimize performance. In RX/TX functions, change code to access only per core data. - Add below API to allow user to use vhost library APIs for a port managed by vhost PMD. There are a bit of limitations. See "rte_eth_vhost.h". - rte_eth_vhost_portid2vdev() To support this functionality, vhost library is also changed. Anyway, if users doesn't use vhost PMD, can fully use vhost library APIs. - Add code to support vhost multiple queues. Actually, multiple queues functionality is not enabled so far. Tetsuya Mukawa (2): vhost: Add callback and private data for vhost PMD vhost: Add VHOST PMD config/common_linuxapp| 6 + drivers/net/Makefile | 4 + drivers/net/vhost/Makefile| 62 +++ drivers/net/vhost/rte_eth_vhost.c | 735 ++ drivers/net/vhost/rte_eth_vhost.h | 65 +++ drivers/net/vhost/rte_pmd_vhost_version.map | 8 + lib/librte_vhost/rte_virtio_net.h | 3 + lib/librte_vhost/vhost_user/virtio-net-user.c | 8 +- lib/librte_vhost/virtio-net.c | 40 +- lib/librte_vhost/virtio-net.h | 3 +- mk/rte.app.mk | 8 +- 11 files changed, 934 insertions(+), 8 deletions(-) create mode 100644 drivers/net/vhost/Makefile create mode 100644 drivers/net/vhost/rte_eth_vhost.c create mode 100644 drivers/net/vhost/rte_eth_vhost.h create mode 100644 drivers/net/vhost/rte_pmd_vhost_version.map -- 2.1.4
[dpdk-dev] [RFC PATCH v3 1/2] vhost: Add callback and private data for vhost PMD
These variables are needed to be able to manage one of virtio devices using both vhost library APIs and vhost PMD. For example, if vhost PMD uses current callback handler and private data provided by vhost library, A DPDK application that links vhost library cannot use some of vhost library APIs. To avoid it, callback and private data for vhost PMD are needed. Signed-off-by: Tetsuya Mukawa --- lib/librte_vhost/rte_virtio_net.h | 3 ++ lib/librte_vhost/vhost_user/virtio-net-user.c | 8 +++--- lib/librte_vhost/virtio-net.c | 40 +-- lib/librte_vhost/virtio-net.h | 3 +- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index 93d3e27..ec84c9b 100644 --- a/lib/librte_vhost/rte_virtio_net.h +++ b/lib/librte_vhost/rte_virtio_net.h @@ -108,6 +108,7 @@ struct virtio_net { uint32_tvirt_qp_nb; uint32_tmem_idx;/** Used in set memory layout, unique for each queue within virtio device. */ void*priv; /**< private context */ + void*pmd_priv; /**< private context for vhost PMD */ } __rte_cache_aligned; /** @@ -198,6 +199,8 @@ int rte_vhost_driver_unregister(const char *dev_name); /* Register callbacks. */ int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const); +/* Register callbacks for vhost PMD (Only for internal). */ +int rte_vhost_driver_pmd_callback_register(struct virtio_net_device_ops const * const); /* Start vhost driver session blocking loop. */ int rte_vhost_driver_session_start(void); diff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c index 6a12d96..a75697f 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.c +++ b/lib/librte_vhost/vhost_user/virtio-net-user.c @@ -288,7 +288,7 @@ user_set_vring_kick(struct vhost_device_ctx ctx, struct VhostUserMsg *pmsg) if (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) - notify_ops->new_device(dev); + notify_new_device(dev); } /* @@ -302,7 +302,7 @@ user_get_vring_base(struct vhost_device_ctx ctx, /* We have to stop the queue (virtio) if it is running. */ if (dev->flags & VIRTIO_DEV_RUNNING) - notify_ops->destroy_device(dev); + notify_destroy_device(dev); /* Here we are safe to get the last used index */ ops->get_vring_base(ctx, state->index, state); @@ -333,7 +333,7 @@ user_reset_owner(struct vhost_device_ctx ctx, /* We have to stop the queue (virtio) if it is running. */ if (dev->flags & VIRTIO_DEV_RUNNING) - notify_ops->destroy_device(dev); + notify_destroy_device(dev); RTE_LOG(INFO, VHOST_CONFIG, "reset owner --- state idx:%d state num:%d\n", state->index, state->num); @@ -379,7 +379,7 @@ user_destroy_device(struct vhost_device_ctx ctx) uint32_t i; if (dev && (dev->flags & VIRTIO_DEV_RUNNING)) - notify_ops->destroy_device(dev); + notify_destroy_device(dev); for (i = 0; i < dev->virt_qp_nb; i++) if (dev && dev->mem_arr[i]) { diff --git a/lib/librte_vhost/virtio-net.c b/lib/librte_vhost/virtio-net.c index 3131719..eec3c22 100644 --- a/lib/librte_vhost/virtio-net.c +++ b/lib/librte_vhost/virtio-net.c @@ -64,6 +64,8 @@ struct virtio_net_config_ll { /* device ops to add/remove device to/from data core. */ struct virtio_net_device_ops const *notify_ops; +/* device ops for vhost PMD to add/remove device to/from data core. */ +struct virtio_net_device_ops const *pmd_notify_ops; /* root address of the linked list of managed virtio devices */ static struct virtio_net_config_ll *ll_root; @@ -84,6 +86,29 @@ static uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES; static uint64_t VHOST_PROTOCOL_FEATURES = VHOST_SUPPORTED_PROTOCOL_FEATURES; +int +notify_new_device(struct virtio_net *dev) +{ + if ((pmd_notify_ops != NULL) && (pmd_notify_ops->new_device != NULL)) { + int ret = pmd_notify_ops->new_device(dev); + if (ret != 0) + return ret; + } + if ((notify_ops != NULL) && (notify_ops->new_device != NULL)) + return notify_ops->new_device(dev); + + return 0; +} + +void +notify_destroy_device(volatile struct virtio_net *dev) +{ + if ((pmd_notify_ops != NULL) && (pmd_notify_ops->destroy_device != NULL)) + pmd_notify_ops->destroy_device(dev); + if ((notify_ops != NULL) && (notify_ops->destroy_device != NULL)) + notify_ops->destroy_device(dev); +} + /* * Converts QEMU virtual address to Vhost virtual address. This function is * used to convert the ring addresses to our address space. @@ -
[dpdk-dev] [RFC PATCH v3 2/2] vhost: Add VHOST PMD
The patch introduces a new PMD. This PMD is implemented as thin wrapper of librte_vhost. It means librte_vhost is also needed to compile the PMD. The vhost messages will be handled only when a port is started. So start a port first, then invoke QEMU. The PMD has 2 parameters. - iface: The parameter is used to specify a path connect to a virtio-net device. - queues: The parameter is used to specify the number of the queues virtio-net device has. (Default: 1) Here is an example. $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0,queues=3' -- -i To connect above testpmd, here is qemu command example. $ qemu-system-x86_64 \ -chardev socket,id=chr0,path=/tmp/sock0 \ -netdev vhost-user,id=net0,chardev=chr0,vhostforce \ -device virtio-net-pci,netdev=net0 Signed-off-by: Tetsuya Mukawa --- config/common_linuxapp | 6 + drivers/net/Makefile| 4 + drivers/net/vhost/Makefile | 62 +++ drivers/net/vhost/rte_eth_vhost.c | 735 drivers/net/vhost/rte_eth_vhost.h | 65 +++ drivers/net/vhost/rte_pmd_vhost_version.map | 8 + mk/rte.app.mk | 8 +- 7 files changed, 887 insertions(+), 1 deletion(-) create mode 100644 drivers/net/vhost/Makefile create mode 100644 drivers/net/vhost/rte_eth_vhost.c create mode 100644 drivers/net/vhost/rte_eth_vhost.h create mode 100644 drivers/net/vhost/rte_pmd_vhost_version.map diff --git a/config/common_linuxapp b/config/common_linuxapp index 0de43d5..7310240 100644 --- a/config/common_linuxapp +++ b/config/common_linuxapp @@ -446,6 +446,12 @@ CONFIG_RTE_LIBRTE_VHOST_NUMA=n CONFIG_RTE_LIBRTE_VHOST_DEBUG=n # +# Compile vhost PMD +# To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled. +# +CONFIG_RTE_LIBRTE_PMD_VHOST=y + +# #Compile Xen domain0 support # CONFIG_RTE_LIBRTE_XEN_DOM0=n diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 5ebf963..e46a38e 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -49,5 +49,9 @@ DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3 DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt +ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y) +DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost +endif # $(CONFIG_RTE_LIBRTE_VHOST) + include $(RTE_SDK)/mk/rte.sharelib.mk include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/drivers/net/vhost/Makefile b/drivers/net/vhost/Makefile new file mode 100644 index 000..8186a80 --- /dev/null +++ b/drivers/net/vhost/Makefile @@ -0,0 +1,62 @@ +# BSD LICENSE +# +# Copyright (c) 2010-2015 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_vhost.a + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +EXPORT_MAP := rte_pmd_vhost_version.map + +LIBABIVER := 1 + +# +# all source are stored in SRCS-y +# +SRCS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += rte_eth_vhost.c + +# +# Export include files +# +SYMLINK-y-include += rte_eth_vhost.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_kvargs +DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += lib/librte_vhost + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/
[dpdk-dev] [PATCH v7 4/8] vhost: rxtx: use queue id instead of constant ring index
On Wed, Oct 21, 2015 at 05:26:18PM +0300, Michael S. Tsirkin wrote: > On Wed, Oct 21, 2015 at 08:48:15PM +0800, Yuanhan Liu wrote: > > > Please note that for virtio devices, guest is supposed to > > > control the placement of incoming packets in RX queues. > > > > I may not follow you. > > > > Enqueuing packets to a RX queue is done at vhost lib, outside the > > guest, how could the guest take the control here? > > > > --yliu > > vhost should do what guest told it to. > > See virtio spec: > 5.1.6.5.5 Automatic receive steering in multiqueue mode Spec says: After the driver transmitted a packet of a flow on transmitqX, the device SHOULD cause incoming packets for that flow to be steered to receiveqX. Michael, I still have no idea how vhost could know the flow even after discussion with Huawei. Could you be more specific about this? Say, how could guest know that? And how could guest tell vhost which RX is gonna to use? Thanks. --yliu
[dpdk-dev] [PATCH v7 3/8] vhost: vring queue setup for multiple queue support
On 10/21/2015 11:48 AM, Yuanhan Liu wrote: > All queue pairs, including the default (the first) queue pair, > are allocated dynamically, when a vring_call message is received > first time for a specific queue pair. > > This is a refactor work for enabling vhost-user multiple queue; > it should not break anything as it does no functional changes: > we don't support mq set, so there is only one mq at max. > > This patch is based on Changchun's patch. > [...] > > void > @@ -290,13 +298,9 @@ user_get_vring_base(struct vhost_device_ctx ctx, >* sent and only sent in vhost_vring_stop. >* TODO: cleanup the vring, it isn't usable since here. >*/ > - if ((dev->virtqueue[VIRTIO_RXQ]->kickfd) >= 0) { > - close(dev->virtqueue[VIRTIO_RXQ]->kickfd); > - dev->virtqueue[VIRTIO_RXQ]->kickfd = -1; > - } > - if ((dev->virtqueue[VIRTIO_TXQ]->kickfd) >= 0) { > - close(dev->virtqueue[VIRTIO_TXQ]->kickfd); > - dev->virtqueue[VIRTIO_TXQ]->kickfd = -1; > + if ((dev->virtqueue[state->index]->kickfd) >= 0) { > + close(dev->virtqueue[state->index]->kickfd); > + dev->virtqueue[state->index]->kickfd = -1; > } Since we change the behavior here, better list in the commit message as well. > > > @@ -680,13 +704,21 @@ set_vring_call(struct vhost_device_ctx ctx, struct > vhost_vring_file *file) > { > struct virtio_net *dev; > struct vhost_virtqueue *vq; > + uint32_t cur_qp_idx = file->index / VIRTIO_QNUM; > > dev = get_device(ctx); > if (dev == NULL) > return -1; > > + /* alloc vring queue pair if it is a new queue pair */ > + if (cur_qp_idx + 1 > dev->virt_qp_nb) { > + if (alloc_vring_queue_pair(dev, cur_qp_idx) < 0) > + return -1; > + } > + Here we rely on the fact that this set_vring_call message is sent in the continuous ascending order of queue idx 0, 1, 2, ... > /* file->index refers to the queue index. The txq is 1, rxq is 0. */ > vq = dev->virtqueue[file->index]; > + assert(vq != NULL); > If we allocate the queue until the we receive the first vring message, better add comment that we rely on this fact. Could we add the vhost-user message to tell us the queue number QEMU allocates before vring message? > if (vq->callfd >= 0) > close(vq->callfd);
[dpdk-dev] [RFC PATCH v2] vhost: Add VHOST PMD
On 2015/10/21 19:22, Bruce Richardson wrote: > On Wed, Oct 21, 2015 at 09:25:12AM +0300, Panu Matilainen wrote: >> On 10/21/2015 07:35 AM, Tetsuya Mukawa wrote: >>> On 2015/10/19 22:27, Richardson, Bruce wrote: > -Original Message- > From: Panu Matilainen [mailto:pmatilai at redhat.com] > Sent: Monday, October 19, 2015 2:26 PM > To: Tetsuya Mukawa ; Richardson, Bruce > ; Loftus, Ciara > Cc: dev at dpdk.org; ann.zhuangyanying at huawei.com > Subject: Re: [dpdk-dev] [RFC PATCH v2] vhost: Add VHOST PMD > > On 10/19/2015 01:50 PM, Tetsuya Mukawa wrote: >> On 2015/10/19 18:45, Bruce Richardson wrote: >>> On Mon, Oct 19, 2015 at 10:32:50AM +0100, Loftus, Ciara wrote: > On 2015/10/16 21:52, Bruce Richardson wrote: >> On Mon, Aug 31, 2015 at 12:55:26PM +0900, Tetsuya Mukawa wrote: >>> The patch introduces a new PMD. This PMD is implemented as thin > wrapper >>> of librte_vhost. It means librte_vhost is also needed to compile > the PMD. >>> The PMD can have 'iface' parameter like below to specify a path >>> to > connect >>> to a virtio-net device. >>> >>> $ ./testpmd -c f -n 4 --vdev 'eth_vhost0,iface=/tmp/sock0' -- -i >>> >>> To connect above testpmd, here is qemu command example. >>> >>> $ qemu-system-x86_64 \ >>> >>> -chardev socket,id=chr0,path=/tmp/sock0 \ >>> -netdev vhost-user,id=net0,chardev=chr0,vhostforce \ >>> -device virtio-net-pci,netdev=net0 >>> >>> Signed-off-by: Tetsuya Mukawa >> With this PMD in place, is there any need to keep the existing >> vhost library around as a separate entity? Can the existing >> library be > subsumed/converted into >> a standard PMD? >> >> /Bruce > Hi Bruce, > > I concern about whether the PMD has all features of librte_vhost, > because librte_vhost provides more features and freedom than ethdev > API provides. > In some cases, user needs to choose limited implementation without > librte_vhost. > I am going to eliminate such cases while implementing the PMD. > But I don't have strong belief that we can remove librte_vhost now. > > So how about keeping current separation in next DPDK? > I guess people will try to replace librte_vhost to vhost PMD, > because apparently using ethdev APIs will be useful in many cases. > And we will get feedbacks like "vhost PMD needs to support like this > usage". > (Or we will not have feedbacks, but it's also OK.) Then, we will be > able to merge librte_vhost and vhost PMD. I agree with the above. One the concerns I had when reviewing the > patch was that the PMD removes some freedom that is available with the > library. Eg. Ability to implement the new_device and destroy_device > callbacks. If using the PMD you are constrained to the implementations of > these in the PMD driver, but if using librte_vhost, you can implement your > own with whatever functionality you like - a good example of this can be > seen in the vhost sample app. On the other hand, the PMD is useful in that it removes a lot of > complexity for the user and may work for some more general use cases. So I > would be in favour of having both options available too. Ciara >>> Thanks. >>> However, just because the libraries are merged does not mean that you >>> need be limited by PMD functionality. Many PMDs provide additional >>> library-specific functions over and above their PMD capabilities. The >>> bonded PMD is a good example here, as it has a whole set of extra >>> functions to create and manipulate bonded devices - things that are >>> obviously not part of the general ethdev API. Other vPMDs similarly > include functions to allow them to be created on the fly too. >>> regards, >>> /Bruce >> Hi Bruce, >> >> I appreciate for showing a good example. I haven't noticed the PMD. >> I will check the bonding PMD, and try to remove librte_vhost without >> losing freedom and features of the library. > Hi, > > Just a gentle reminder - if you consider removing (even if by just > replacing/renaming) an entire library, it needs to happen the ABI > deprecation process. > > It seems obvious enough. But for all the ABI policing here, somehow we all > failed to notice the two compatibility breaking rename-elephants in the > room during 2.1 development: > - libintel_dpdk was renamed to libdpdk > - librte_pmd_virtio_uio was renamed to librte_pmd_virtio > > Of course these cases are easy to work around with symlinks, and are > unrelated to the matter at hand. Just wa
[dpdk-dev] [PATCH v7 1/8] vhost-user: add protocol features support
On 10/21/2015 11:48 AM, Yuanhan Liu wrote: [...] > > VHOST_USER_PROTOCOL_FEATURES is initated to 0, as we don't support > s/initiated/initialized/
[dpdk-dev] Inconsistent statistics counters for pmd_i40e
Arnon Warshavsky wrote on 10/19/2015 03:46:22 PM: > From: Arnon Warshavsky > To: Eimear Morrissey/Ireland/IBM at IBMIE > Cc: dev at dpdk.org > Date: 10/19/2015 03:46 PM > Subject: Re: [dpdk-dev] Inconsistent statistics counters for pmd_i40e > > Hi Eimear > > This is the link I have. > https://downloadcenter.intel.com/download/24769 > > I guess that the version seen in the web page comes from a different > parallel universe. > You should see the actual fw version inside the zip file. > Thanks > /Arnon > > On Mon, Oct 19, 2015 at 5:30 PM, Eimear Morrissey > wrote: > Arnon Warshavsky wrote on 10/19/2015 03:01:46 PM: > > > From: Arnon Warshavsky > > To: Eimear Morrissey/Ireland/IBM at IBMIE > > Cc: dev at dpdk.org > > Date: 10/19/2015 03:01 PM > > Subject: Re: [dpdk-dev] Inconsistent statistics counters for pmd_i40e > > > > > Hi Eimear, > > > > I just experienced the same problem with firmware versions 4.23 and > > 4.33 (dpdk 2.0). Did not get to try the latest which is 4.5. > > Looking at the code, I don't see that this counter is being read any > > differently than its peer counters and I suspect the nic itself. > > Can you tell which firmware version you were using? > > > > thanks > > /Arnon > > > > On Mon, Oct 19, 2015 at 2:43 PM, Eimear Morrissey < > eimear.morrissey at ie.ibm.com > > > wrote: > > > > > > Hi, > > > > I'm having issues measuring packets dropped at the NIC in both the 2.0.0 > > and 2.1.0 versions of DPDK on an X710 Intel NIC. > > > > In dpdk-2.0.0 > > Using rte_eth_xstats the rx_packets and rx_bytes counters increase as > > expected, however rx_missed_errors is always 0 even if a sleep statement is > > added between calls to rte_eth_rx_burst. However changing the coremask so > > the application is running on a different socket than the card will cause > > rx_missed_errors to increment for a limited amount of time and then stop. > > Using rte_eth_stats, ipackets is incremented on packet receipt but the > > q_ipackets and q_errors arrays remain zero. Even crossing sockets seems to > > have no effect on q_errors. > > > > In dpdk-2.1.0 the behaviour is the same as above, except that the number of > > fields returned by rte_eth_xstats_get is reduced (no rx_missed errors at > > all) so running on a different socket no longer has any noticeable effect > > on the stats. > > > > My understanding from the API manual is that the rte_eth_stats q_errors > > array should count the packets missed because software isn't polling fast > > enough, but that doesn't seem to be the case? Is there a standard DPDK way > > to check this? The application is a forwarding one so there's no other way > > to estimate drop except through NIC rx. > > > > Thanks, > > Eimear > > > > > > > > -- > > > > Arnon Warshavsky > > Qwilt | work: +972-72-2221634 | mobile: +972-50-8583058 | arnon at qwilt.com > Hi Arnon, > > The firmware version I'm using is 4.26. Where do you see the latest > is 4.5 - I can't find anything obvious in the download centre? > > Regards, > Eimear > > > > -- > > Arnon Warshavsky > Qwilt | work: +972-72-2221634 | mobile: +972-50-8583058 | arnon at qwilt.com I tried installing the firmware but on running the NVM update tool I just get "No updates available for your device" which makes me think that (for my SKU at least) I'm on the latest firmware. Also, if I bind the card back to the i40e driver, I can force the dropped count in ifconfig to increase by decreasing the rx ring size so I'm not convinced it's entirely a hardware issue. Regards, Eimear
[dpdk-dev] [PATCH] tools: exit setup script without prompt
Exit tools/setup.sh script without prompting "Press enter to continue". The script can now be exited by typing the option number, "quit" or "q". Signed-off-by: John McNamara --- tools/setup.sh | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/setup.sh b/tools/setup.sh index 5a8b2f3..fbd3853 100755 --- a/tools/setup.sh +++ b/tools/setup.sh @@ -57,6 +57,12 @@ quit() QUIT=$1 } +# Shortcut for quit. +q() +{ + quit +} + # # Sets up environmental variables for ICC. # @@ -628,6 +634,10 @@ while [ "$QUIT" == "0" ]; do read our_entry echo "" ${OPTIONS[our_entry]} ${our_entry} - echo - echo -n "Press enter to continue ..."; read + + if [ "$QUIT" == "0" ] ; then + echo + echo -n "Press enter to continue ..."; read + fi + done -- 1.8.1.4
[dpdk-dev] [PATCH v2 0/5] virtio: Tx performance improvements
On 10/21/2015 9:20 PM, Thomas Monjalon wrote: > 2015-10-18 22:16, Stephen Hemminger: >> This is a tested version of the virtio Tx performance improvements >> that I posted earlier on the list, and described at the DPDK Userspace >> meeting in Dublin. Together they get a 25% performance improvement for >> both small packet and large multi-segment packet case when testing >> from DPDK guest application to Linux KVM host. >> >> Stephen Hemminger (5): >> virtio: clean up space checks on xmit >> virtio: don't use unlikely for normal tx stuff >> virtio: use indirect ring elements >> virtio: use any layout on transmit >> virtio: optimize transmit enqueue > Huawei, do you ack this series? > Okay with this patchset with two remained questions, +/* Region reserved to allow for transmit header and indirect ring */ +#define VIRTIO_MAX_TX_INDIRECT 8 +struct virtio_tx_region { + struct virtio_net_hdr_mrg_rxbuf tx_hdr; Why use merge-able rx header here in the tx region? > + struct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT] > +__attribute__((__aligned__(16))); WARNING: __aligned(size) is preferred over __attribute__((aligned(size))) [...]
[dpdk-dev] ixgbe: ierrors counter spuriously increasing in DPDK 2.1
Hi Martin, We agreed on the main point: it's an issue. IMO the implementation details are up to Maryam. There have been few patches, so I guess it will be fixed in 2.2. Andriy On Thu, Oct 22, 2015 at 9:46 AM, Martin Weiser wrote: > Hi Andriy, > > thank you for pointing this discussion out to me. I somehow missed it. > Unfortunately it looks like the discussion stopped after Maryam made a > good proposal so I will vote in on that and hopefully get things started > again. > > Best regards, > Martin > > > > On 21.10.15 17:53, Andriy Berestovskyy wrote: >> Yes Marcin, >> The issue was discussed here: >> http://dpdk.org/ml/archives/dev/2015-September/023229.html >> >> You can either fix the ierrors in ixgbe_dev_stats_get() or implement a >> workaround in your app getting the extended statistics and counting >> out some of extended counters from the ierrors. >> >> Here is an example: >> https://github.com/Juniper/contrail-vrouter/commit/72f6ca05ac81d0ca5e7eb93c6ffe7a93648c2b00#diff-99c1f65a00658c7d38b3d1b64cb5fd93R1306 >> >> Regards, >> Andriy >> >> On Wed, Oct 21, 2015 at 10:38 AM, Martin Weiser >> wrote: >>> Hi, >>> >>> with DPDK 2.1 we are seeing the ierrors counter increasing for 82599ES >>> ports without reason. Even directly after starting test-pmd the error >>> counter immediately is 1 without even a single packet being sent to the >>> device: >>> >>> ./testpmd -c 0xfe -n 4 -- --portmask 0x3 --interactive >>> ... >>> testpmd> show port stats all >>> >>> NIC statistics for port 0 >>> >>> RX-packets: 0 RX-missed: 0 RX-bytes: 0 >>> RX-badcrc: 0 RX-badlen: 0 RX-errors: 1 >>> RX-nombuf: 0 >>> TX-packets: 0 TX-errors: 0 TX-bytes: 0 >>> >>> >>> >>> NIC statistics for port 1 >>> >>> RX-packets: 0 RX-missed: 0 RX-bytes: 0 >>> RX-badcrc: 0 RX-badlen: 0 RX-errors: 1 >>> RX-nombuf: 0 >>> TX-packets: 0 TX-errors: 0 TX-bytes: 0 >>> >>> >>> >>> >>> When packet forwarding is started the ports perform normally and >>> properly forward all packets but a huge number of ierrors is counted: >>> >>> testpmd> start >>> ... >>> testpmd> show port stats all >>> >>> NIC statistics for port 0 >>> >>> RX-packets: 9011857RX-missed: 0 RX-bytes: 5020932992 >>> RX-badcrc: 0 RX-badlen: 0 RX-errors: 9011753 >>> RX-nombuf: 0 >>> TX-packets: 9026250TX-errors: 0 TX-bytes: 2922375542 >>> >>> >>> >>> NIC statistics for port 1 >>> >>> RX-packets: 9026250RX-missed: 0 RX-bytes: 2922375542 >>> RX-badcrc: 0 RX-badlen: 0 RX-errors: 9026138 >>> RX-nombuf: 0 >>> TX-packets: 9011857TX-errors: 0 TX-bytes: 5020932992 >>> >>> >>> >>> >>> When running the exact same test with DPDK version 2.0 no ierrors are >>> reported. >>> Is anyone else seeing strange ierrors being reported for Intel Niantic >>> cards with DPDK 2.1? >>> >>> Best regards, >>> Martin >>> >> >> > > -- Andriy Berestovskyy
[dpdk-dev] Inconsistent statistics counters for pmd_i40e
You are right. Given this thread updated today http://dpdk.org/ml/archives/dev/2015-September/023480.html (updates from today still not there) It seems I was too quick to jump to conclusion. Just in case, when bound to i40e, can you run ethtool -i on that interface? It should show the fw version. thanks /Arnon On Thu, Oct 22, 2015 at 12:57 PM, Eimear Morrissey < eimear.morrissey at ie.ibm.com> wrote: > Arnon Warshavsky wrote on 10/19/2015 03:46:22 PM: > > > From: Arnon Warshavsky > > To: Eimear Morrissey/Ireland/IBM at IBMIE > > Cc: dev at dpdk.org > > Date: 10/19/2015 03:46 PM > > > Subject: Re: [dpdk-dev] Inconsistent statistics counters for pmd_i40e > > > > Hi Eimear > > > > This is the link I have. > > https://downloadcenter.intel.com/download/24769 > > > > I guess that the version seen in the web page comes from a different > > parallel universe. > > You should see the actual fw version inside the zip file. > > > Thanks > > /Arnon > > > > On Mon, Oct 19, 2015 at 5:30 PM, Eimear Morrissey < > eimear.morrissey at ie.ibm.com > > > wrote: > > Arnon Warshavsky wrote on 10/19/2015 03:01:46 PM: > > > > > From: Arnon Warshavsky > > > To: Eimear Morrissey/Ireland/IBM at IBMIE > > > Cc: dev at dpdk.org > > > Date: 10/19/2015 03:01 PM > > > Subject: Re: [dpdk-dev] Inconsistent statistics counters for pmd_i40e > > > > > > > > Hi Eimear, > > > > > > I just experienced the same problem with firmware versions 4.23 and > > > 4.33 (dpdk 2.0). Did not get to try the latest which is 4.5. > > > Looking at the code, I don't see that this counter is being read any > > > differently than its peer counters and I suspect the nic itself. > > > Can you tell which firmware version you were using? > > > > > > thanks > > > /Arnon > > > > > > On Mon, Oct 19, 2015 at 2:43 PM, Eimear Morrissey < > > eimear.morrissey at ie.ibm.com > > > > wrote: > > > > > > > > > Hi, > > > > > > I'm having issues measuring packets dropped at the NIC in both the > 2.0.0 > > > and 2.1.0 versions of DPDK on an X710 Intel NIC. > > > > > > In dpdk-2.0.0 > > > Using rte_eth_xstats the rx_packets and rx_bytes counters increase as > > > expected, however rx_missed_errors is always 0 even if a sleep > statement is > > > added between calls to rte_eth_rx_burst. However changing the coremask > so > > > the application is running on a different socket than the card will > cause > > > rx_missed_errors to increment for a limited amount of time and then > stop. > > > Using rte_eth_stats, ipackets is incremented on packet receipt but the > > > q_ipackets and q_errors arrays remain zero. Even crossing sockets > seems to > > > have no effect on q_errors. > > > > > > In dpdk-2.1.0 the behaviour is the same as above, except that the > number of > > > fields returned by rte_eth_xstats_get is reduced (no rx_missed errors > at > > > all) so running on a different socket no longer has any noticeable > effect > > > on the stats. > > > > > > My understanding from the API manual is that the rte_eth_stats q_errors > > > array should count the packets missed because software isn't polling > fast > > > enough, but that doesn't seem to be the case? Is there a standard DPDK > way > > > to check this? The application is a forwarding one so there's no other > way > > > to estimate drop except through NIC rx. > > > > > > Thanks, > > > Eimear > > > > > > > > > > > > -- > > > > > > Arnon Warshavsky > > > Qwilt | work: +972-72-2221634 | mobile: +972-50-8583058 | > arnon at qwilt.com > > > Hi Arnon, > > > > The firmware version I'm using is 4.26. Where do you see the latest > > is 4.5 - I can't find anything obvious in the download centre? > > > > Regards, > > Eimear > > > > > > > > -- > > > > Arnon Warshavsky > > Qwilt | work: +972-72-2221634 | mobile: +972-50-8583058 | > arnon at qwilt.com > > > I tried installing the firmware but on running the NVM update tool I just > get "No updates available for your device" which makes me think that (for > my SKU at least) I'm on the latest firmware. > > Also, if I bind the card back to the i40e driver, I can force the dropped > count in ifconfig to increase by decreasing the rx ring size so I'm not > convinced it's entirely a hardware issue. > > Regards, > Eimear > > -- *Arnon Warshavsky* *Qwilt | work: +972-72-2221634 | mobile: +972-50-8583058 | arnon at qwilt.com *
[dpdk-dev] [PATCH v7 3/8] vhost: vring queue setup for multiple queue support
On Thu, Oct 22, 2015 at 09:49:58AM +, Xie, Huawei wrote: > On 10/21/2015 11:48 AM, Yuanhan Liu wrote: > > All queue pairs, including the default (the first) queue pair, > > are allocated dynamically, when a vring_call message is received > > first time for a specific queue pair. > > > > This is a refactor work for enabling vhost-user multiple queue; > > it should not break anything as it does no functional changes: > > we don't support mq set, so there is only one mq at max. > > > > This patch is based on Changchun's patch. > > > [...] > > > > void > > @@ -290,13 +298,9 @@ user_get_vring_base(struct vhost_device_ctx ctx, > > * sent and only sent in vhost_vring_stop. > > * TODO: cleanup the vring, it isn't usable since here. > > */ > > - if ((dev->virtqueue[VIRTIO_RXQ]->kickfd) >= 0) { > > - close(dev->virtqueue[VIRTIO_RXQ]->kickfd); > > - dev->virtqueue[VIRTIO_RXQ]->kickfd = -1; > > - } > > - if ((dev->virtqueue[VIRTIO_TXQ]->kickfd) >= 0) { > > - close(dev->virtqueue[VIRTIO_TXQ]->kickfd); > > - dev->virtqueue[VIRTIO_TXQ]->kickfd = -1; > > + if ((dev->virtqueue[state->index]->kickfd) >= 0) { > > + close(dev->virtqueue[state->index]->kickfd); > > + dev->virtqueue[state->index]->kickfd = -1; > > } > Since we change the behavior here, better list in the commit message as > well. I checked the code again, and found I should not change that: GET_VRING_BASE is sent per virt queue pair. BTW, it's wrong to do this kind of stuff here, we need fix it in future. > > > > > > > @@ -680,13 +704,21 @@ set_vring_call(struct vhost_device_ctx ctx, struct > > vhost_vring_file *file) > > { > > struct virtio_net *dev; > > struct vhost_virtqueue *vq; > > + uint32_t cur_qp_idx = file->index / VIRTIO_QNUM; > > > > dev = get_device(ctx); > > if (dev == NULL) > > return -1; > > > > + /* alloc vring queue pair if it is a new queue pair */ > > + if (cur_qp_idx + 1 > dev->virt_qp_nb) { > > + if (alloc_vring_queue_pair(dev, cur_qp_idx) < 0) > > + return -1; > > + } > > + > Here we rely on the fact that this set_vring_call message is sent in the > continuous ascending order of queue idx 0, 1, 2, ... That's true. > > > /* file->index refers to the queue index. The txq is 1, rxq is 0. */ > > vq = dev->virtqueue[file->index]; > > + assert(vq != NULL); > > > If we allocate the queue until the we receive the first vring message, > better add comment that we rely on this fact. Will do that. > Could we add the vhost-user message to tell us the queue number QEMU > allocates before vring message? We may need do that. But it's too late to make it in v2.2 --yliu > > if (vq->callfd >= 0) > > close(vq->callfd); >
[dpdk-dev] [PATCH v7 4/8] vhost: rxtx: use queue id instead of constant ring index
On Thu, Oct 22, 2015 at 05:49:55PM +0800, Yuanhan Liu wrote: > On Wed, Oct 21, 2015 at 05:26:18PM +0300, Michael S. Tsirkin wrote: > > On Wed, Oct 21, 2015 at 08:48:15PM +0800, Yuanhan Liu wrote: > > > > Please note that for virtio devices, guest is supposed to > > > > control the placement of incoming packets in RX queues. > > > > > > I may not follow you. > > > > > > Enqueuing packets to a RX queue is done at vhost lib, outside the > > > guest, how could the guest take the control here? > > > > > > --yliu > > > > vhost should do what guest told it to. > > > > See virtio spec: > > 5.1.6.5.5 Automatic receive steering in multiqueue mode > > Spec says: > > After the driver transmitted a packet of a flow on transmitqX, > the device SHOULD cause incoming packets for that flow to be > steered to receiveqX. > > > Michael, I still have no idea how vhost could know the flow even > after discussion with Huawei. Could you be more specific about > this? Say, how could guest know that? And how could guest tell > vhost which RX is gonna to use? > > Thanks. > > --yliu I don't really understand the question. When guests transmits a packet, it makes a decision about the flow to use, and maps that to a tx/rx pair of queues. It sends packets out on the tx queue and expects device to return packets from the same flow on the rx queue. During transmit, device needs to figure out the flow of packets as they are received from guest, and track which flows go on which tx queue. When it selects the rx queue, it has to use the same table. There is currently no provision for controlling steering for uni-directional flows which are possible e.g. with UDP. We might solve this in a future spec - for example, set a flag notifying guest that steering information is missing for a given flow, for example by setting a flag in a packet, or using the command queue, and have guest send a dummy empty packet to set steering rule for this flow. -- MST
[dpdk-dev] [PATCH v3 7/7] virtio: pick simple rx/tx func
On 10/22/2015 10:50 AM, Tan, Jianfeng wrote: > On 10/22/2015 10:45 AM, Jianfeng wrote: > >> -Original Message- >> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Huawei Xie >> Sent: Tuesday, October 20, 2015 11:30 PM >> To: dev at dpdk.org >> Subject: [dpdk-dev] [PATCH v3 7/7] virtio: pick simple rx/tx func >> >> simple rx/tx func is enabled when user specifies single segment and no >> offload support. >> merge-able should be disabled to use simple rxtx. >> >> Signed-off-by: Huawei Xie >> --- >> drivers/net/virtio/virtio_rxtx.c | 12 >> 1 file changed, 12 insertions(+) >> >> diff --git a/drivers/net/virtio/virtio_rxtx.c >> b/drivers/net/virtio/virtio_rxtx.c >> index 947fc46..71f8cd4 100644 >> --- a/drivers/net/virtio/virtio_rxtx.c >> +++ b/drivers/net/virtio/virtio_rxtx.c >> @@ -62,6 +62,10 @@ >> #define VIRTIO_DUMP_PACKET(m, len) do { } while (0) #endif >> >> + >> +#define VIRTIO_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS >> | \ >> +ETH_TXQ_FLAGS_NOOFFLOADS) >> + >> static int use_simple_rxtx; >> >> static void >> @@ -471,6 +475,14 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev >> *dev, >> return -EINVAL; >> } >> >> +/* Use simple rx/tx func if single segment and no offloads */ >> +if ((tx_conf->txq_flags & VIRTIO_SIMPLE_FLAGS) == >> VIRTIO_SIMPLE_FLAGS) { >> +PMD_INIT_LOG(INFO, "Using simple rx/tx path"); >> +dev->tx_pkt_burst = virtio_xmit_pkts_simple; >> +dev->rx_pkt_burst = virtio_recv_pkts_vec; > Whether recv side mergeable is supported is controlled by > virtio_negotiate_feature(). > So "dev->rx_pkt_burst = virtio_recv_pkts_vec" should be restricted by > hw->guest_features & VIRTIO_NET_F_MRG_RXBUF, right? Add this check in next version. However it will still be put here as we want to leave us a chance to dynamically choose normal/simple rx function. > >> +use_simple_rxtx = 1; >> +} >> + >> ret = virtio_dev_queue_setup(dev, VTNET_TQ, queue_idx, >> vtpci_queue_idx, >> nb_desc, socket_id, &vq); >> if (ret < 0) { >> -- >> 1.8.1.4 >
[dpdk-dev] [PATCH v3 2/4] nfp-uio: new uio driver for netronome nfp6000 card
Submitting just the PMD for integration makes sense. I will remove all the references to nfp_uio. My doubt is with documentation. Working with the NFP PMD will not be possible without nfp_uio. We could modify the documentation saying it is possible to use igb_uio, but this is not the right thing to do (pci mask will be wrong). So, would it be acceptable to submit a new PMD without any documentation by now? I prefer this for the sake of integration than giving wrong or incomplete documentation. Thanks On Wed, Oct 21, 2015 at 8:40 PM, Alejandro Lucero < alejandro.lucero at netronome.com> wrote: > > > On Wed, Oct 21, 2015 at 5:03 PM, Thomas Monjalon < > thomas.monjalon at 6wind.com> wrote: > >> 2015-10-21 16:57, Alejandro Lucero: >> > I understand interest for not having another UIO driver does exist. We >> > could maintain an external nfp_uio by now till either we get rid of it >> or >> > we definitely find out it is really needed. any chance to accept >> nfp_uio by >> > now? >> >> No, there are some work currently to get rid of igb_uio. >> So there are little chances to accept nfp_uio one day. >> Please take the first step of integrating your PMD without link interrupt. >> Later we'll be able to discuss how to mitigate the interrupt issue. >> > > Ok. I will create a new patchset version without nfp_uio. > > By the way, that work with igb_uio is about the patches to > pci_uio_generic? I thought there was some reticence from the maintainer for > adding pci bus master there. > > >
[dpdk-dev] volunteer to be the maintainer of driver/net/intel sub-tree
Hi Thomas, > -Original Message- > From: Thomas Monjalon [mailto:thomas.monjalon at 6wind.com] > Sent: Thursday, October 22, 2015 4:17 PM > To: Lu, Wenzhuo > Cc: dev at dpdk.org; Zhang, Helin; Richardson, Bruce > Subject: Re: volunteer to be the maintainer of driver/net/intel sub-tree > > Hi Wenzhuo, > > 2015-10-22 02:49, Lu, Wenzhuo: > > Hi all, > > Following the discussion of DPDK user space and the maintenance of > development sub-trees, I'd like to volunteer myself to be the maintainer of > sub-tree driver/net/intel. It includes all the PMD of Intel NICs. And Helin > can > be my backup. > > Thanks for proposing. > You are already doing part of the work being maintainer of e1000, and Helin > for ixgbe and i40e. > > > I suggest we create a new directory to move the driver/net/e1000, > driver/net/fm10k... to it. And we can also create directories for other > vendors just like the kernel driver do. > > We don't need to move files to be able to manage them in a sub-tree. > For the day to day tasks, it's better to limit directory depth. > And think about what happened with Broadcom and Qlogic, we are not > going to move files when Intel will buy the NIC xyz. > Generally speaking, it's better to keep company names outside of technical > things. > I think you're reasonable. I thought adding a directory may make thing's simple, but the reality is it may introduce something that's out of our control. :) But a single directory also has its benefit, it can easily let us know all the things in the directory is maintained by a or a group of owners. I think the key is how to let the developers know what happens. If something can explain itself, we need not clarify it. Agree we'd better not adding the company name. But I think it's still worth thinking about how to make things more clear. Honestly, I don't have any proposal now. Maybe we have to come out a doc at last. :) > > Additionally, as we observed, some patch sets will not only change the files > in drivers/net, but also some files in lib/librte_ether, doc, app, examples... > Only being drivers/net/intel maintainer cannot work for these patch sets, > especially for the new features. Applying partial feature patch set is not > ideal. > Ideally we need a maintainer to drive the RTE_ETHER discussion. Maybe > Bruce can be a top-level maintainer. So, he can help when we face this > scenario. > > A sub-tree is not restricted to some directories. It must manage an expertise > zone, a technical domain, an area of interest, choose your words ;) > > Today we have no working sub-tree. So we should start splitting areas in > some large grain and make it work. Then we can split more with a top down > approach. > So I think we should first create the subtree for networking drivers and wait > a little before having a subtree for Intel NICs. > > Do you agree? Honestly, I cannot tell which is better that we begin with a big area or a small area. But I agree we should have something working first. It can become a guide . A sub-tree for networking drivers seems to be a good option. If it's not too bothering, I'd like to mention again that the concern is the networking drivers are affinitive with rte_eth.
[dpdk-dev] [PATCHv6 0/9] ethdev: add new API to retrieve RX/TX queue information
Add the ability for the upper layer to query: 1) configured RX/TX queue information. 2) information about RX/TX descriptors min/max/align numbers per queue for the device. v2 changes: - Add formal check for the qinfo input parameter. - As suggested rename 'rx_qinfo/tx_qinfo' to 'rxq_info/txq_info' v3 changes: - Updated rte_ether_version.map - Merged with latest changes v4 changes: - rte_ether_version.map: move new functions into DPDK_2.1 sub-space. v5 changes: - adressed previous code-review comments - rte_ether_version.map: move new functions into DPDK_2.2 sub-space. - added new fields into rte_eth_dev_info v6 chages: - respin to comply with latest dpdk.org - update release_notes Konstantin Ananyev (9): ethdev: add new API to retrieve RX/TX queue information i40e: add support for eth_(rxq|txq)_info_get and (rx|tx)_desc_lim ixgbe: add support for eth_(rxq|txq)_info_get and (rx|tx)_desc_lim e1000: add support for eth_(rxq|txq)_info_get and (rx|tx)_desc_lim testpmd: add new command to display RX/TX queue information fm10k: add HW specific desc_lim data into dev_info cxgbe: add HW specific desc_lim data into dev_info vmxnet3: add HW specific desc_lim data into dev_info doc: release notes update for queue_info_get() app/test-pmd/cmdline.c | 48 +++ app/test-pmd/config.c | 77 ++ app/test-pmd/testpmd.h | 2 + doc/guides/rel_notes/release_2_2.rst | 7 +++ drivers/net/cxgbe/cxgbe_ethdev.c | 9 drivers/net/e1000/e1000_ethdev.h | 36 ++ drivers/net/e1000/em_ethdev.c | 14 ++ drivers/net/e1000/em_rxtx.c| 71 drivers/net/e1000/igb_ethdev.c | 22 + drivers/net/e1000/igb_rxtx.c | 66 +- drivers/net/fm10k/fm10k_ethdev.c | 11 + drivers/net/i40e/i40e_ethdev.c | 14 ++ drivers/net/i40e/i40e_ethdev.h | 5 ++ drivers/net/i40e/i40e_ethdev_vf.c | 12 + drivers/net/i40e/i40e_rxtx.c | 37 +++ drivers/net/ixgbe/ixgbe_ethdev.c | 23 + drivers/net/ixgbe/ixgbe_ethdev.h | 6 +++ drivers/net/ixgbe/ixgbe_rxtx.c | 68 +-- drivers/net/ixgbe/ixgbe_rxtx.h | 21 + drivers/net/vmxnet3/vmxnet3_ethdev.c | 12 + lib/librte_ether/rte_ethdev.c | 68 +++ lib/librte_ether/rte_ethdev.h | 85 +- lib/librte_ether/rte_ether_version.map | 8 23 files changed, 642 insertions(+), 80 deletions(-) -- 1.8.5.3
[dpdk-dev] [PATCHv6 1/9] ethdev: add new API to retrieve RX/TX queue information
From: "Ananyev, Konstantin" Add the ability for the upper layer to query RX/TX queue information. Add into rte_eth_dev_info new fields to represent information about RX/TX descriptors min/max/alig nnumbers per queue for the device. Add new structures: struct rte_eth_rxq_info struct rte_eth_txq_info new functions: rte_eth_rx_queue_info_get rte_eth_tx_queue_info_get into rte_etdev API. Left extra free space in the queue info structures, so extra fields could be added later without ABI breakage. Add new fields: rx_desc_lim tx_desc_lim into rte_eth_dev_info. Signed-off-by: Konstantin Ananyev --- lib/librte_ether/rte_ethdev.c | 68 +++ lib/librte_ether/rte_ethdev.h | 85 +- lib/librte_ether/rte_ether_version.map | 8 3 files changed, 159 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index f593f6e..d18ecb5 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1447,6 +1447,19 @@ rte_eth_rx_queue_setup(uint8_t port_id, uint16_t rx_queue_id, return -EINVAL; } + if (nb_rx_desc > dev_info.rx_desc_lim.nb_max || + nb_rx_desc < dev_info.rx_desc_lim.nb_min || + nb_rx_desc % dev_info.rx_desc_lim.nb_align != 0) { + + PMD_DEBUG_TRACE("Invalid value for nb_rx_desc(=%hu), " + "should be: <= %hu, = %hu, and a product of %hu\n", + nb_rx_desc, + dev_info.rx_desc_lim.nb_max, + dev_info.rx_desc_lim.nb_min, + dev_info.rx_desc_lim.nb_align); + return -EINVAL; + } + if (rx_conf == NULL) rx_conf = &dev_info.default_rxconf; @@ -1786,11 +1799,18 @@ void rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info) { struct rte_eth_dev *dev; + const struct rte_eth_desc_lim lim = { + .nb_max = UINT16_MAX, + .nb_min = 0, + .nb_align = 1, + }; VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; memset(dev_info, 0, sizeof(struct rte_eth_dev_info)); + dev_info->rx_desc_lim = lim; + dev_info->tx_desc_lim = lim; FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get); (*dev->dev_ops->dev_infos_get)(dev, dev_info); @@ -3221,6 +3241,54 @@ rte_eth_remove_tx_callback(uint8_t port_id, uint16_t queue_id, } int +rte_eth_rx_queue_info_get(uint8_t port_id, uint16_t queue_id, + struct rte_eth_rxq_info *qinfo) +{ + struct rte_eth_dev *dev; + + VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + if (qinfo == NULL) + return -EINVAL; + + dev = &rte_eth_devices[port_id]; + if (queue_id >= dev->data->nb_rx_queues) { + PMD_DEBUG_TRACE("Invalid RX queue_id=%d\n", queue_id); + return -EINVAL; + } + + FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rxq_info_get, -ENOTSUP); + + memset(qinfo, 0, sizeof(*qinfo)); + dev->dev_ops->rxq_info_get(dev, queue_id, qinfo); + return 0; +} + +int +rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id, + struct rte_eth_txq_info *qinfo) +{ + struct rte_eth_dev *dev; + + VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + if (qinfo == NULL) + return -EINVAL; + + dev = &rte_eth_devices[port_id]; + if (queue_id >= dev->data->nb_tx_queues) { + PMD_DEBUG_TRACE("Invalid TX queue_id=%d\n", queue_id); + return -EINVAL; + } + + FUNC_PTR_OR_ERR_RET(*dev->dev_ops->txq_info_get, -ENOTSUP); + + memset(qinfo, 0, sizeof(*qinfo)); + dev->dev_ops->txq_info_get(dev, queue_id, qinfo); + return 0; +} + +int rte_eth_dev_set_mc_addr_list(uint8_t port_id, struct ether_addr *mc_addr_set, uint32_t nb_mc_addr) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 8a8c82b..4d7b6f2 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -653,6 +653,15 @@ struct rte_eth_txconf { }; /** + * A structure contains information about HW descriptor ring limitations. + */ +struct rte_eth_desc_lim { + uint16_t nb_max; /**< Max allowed number of descriptors. */ + uint16_t nb_min; /**< Min allowed number of descriptors. */ + uint16_t nb_align; /**< Number of descriptors should be aligned to. */ +}; + +/** * This enum indicates the flow control mode */ enum rte_eth_fc_mode { @@ -837,6 +846,8 @@ struct rte_eth_dev_info { uint16_t vmdq_queue_base; /**< First queue ID for VMDQ pools. */ uint16_t vmdq_queue_num; /**< Queue number for VMDQ pools. */ uint16_t vmdq_pool_base; /**< First ID of VMDQ pools. */ + struct rte_eth_desc_lim rx_desc_lim; /**< RX descrip
[dpdk-dev] [PATCHv6 6/9] cxgbe: add HW specific desc_lim data into dev_info
Signed-off-by: Konstantin Ananyev --- drivers/net/cxgbe/cxgbe_ethdev.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c index a8e057b..920e071 100644 --- a/drivers/net/cxgbe/cxgbe_ethdev.c +++ b/drivers/net/cxgbe/cxgbe_ethdev.c @@ -141,6 +141,12 @@ static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev, struct adapter *adapter = pi->adapter; int max_queues = adapter->sge.max_ethqsets / adapter->params.nports; + static const struct rte_eth_desc_lim cxgbe_desc_lim = { + .nb_max = CXGBE_MAX_RING_DESC_SIZE, + .nb_min = CXGBE_MIN_RING_DESC_SIZE, + .nb_align = 1, + }; + device_info->min_rx_bufsize = CXGBE_MIN_RX_BUFSIZE; device_info->max_rx_pktlen = CXGBE_MAX_RX_PKTLEN; device_info->max_rx_queues = max_queues; @@ -162,6 +168,9 @@ static void cxgbe_dev_info_get(struct rte_eth_dev *eth_dev, DEV_TX_OFFLOAD_TCP_TSO; device_info->reta_size = pi->rss_size; + + device_info->rx_desc_lim = cxgbe_desc_lim; + device_info->tx_desc_lim = cxgbe_desc_lim; } static void cxgbe_dev_promiscuous_enable(struct rte_eth_dev *eth_dev) -- 1.8.5.3
[dpdk-dev] [PATCHv6 4/9] e1000: add support for eth_(rxq|txq)_info_get and (rx|tx)_desc_lim
Signed-off-by: Konstantin Ananyev --- drivers/net/e1000/e1000_ethdev.h | 36 drivers/net/e1000/em_ethdev.c| 14 drivers/net/e1000/em_rxtx.c | 71 +++- drivers/net/e1000/igb_ethdev.c | 22 + drivers/net/e1000/igb_rxtx.c | 66 - 5 files changed, 156 insertions(+), 53 deletions(-) diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h index 4e69e44..3c6f613 100644 --- a/drivers/net/e1000/e1000_ethdev.h +++ b/drivers/net/e1000/e1000_ethdev.h @@ -108,6 +108,30 @@ ETH_RSS_IPV6_TCP_EX | \ ETH_RSS_IPV6_UDP_EX) +/* + * Maximum number of Ring Descriptors. + * + * Since RDLEN/TDLEN should be multiple of 128 bytes, the number of ring + * desscriptors should meet the following condition: + * (num_ring_desc * sizeof(struct e1000_rx/tx_desc)) % 128 == 0 + */ +#defineE1000_MIN_RING_DESC 32 +#defineE1000_MAX_RING_DESC 4096 + +/* + * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be + * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. + * This will also optimize cache line size effect. + * H/W supports up to cache line size 128. + */ +#defineE1000_ALIGN 128 + +#defineIGB_RXD_ALIGN (E1000_ALIGN / sizeof(union e1000_adv_rx_desc)) +#defineIGB_TXD_ALIGN (E1000_ALIGN / sizeof(union e1000_adv_tx_desc)) + +#defineEM_RXD_ALIGN(E1000_ALIGN / sizeof(struct e1000_rx_desc)) +#defineEM_TXD_ALIGN(E1000_ALIGN / sizeof(struct e1000_data_desc)) + /* structure for interrupt relative data */ struct e1000_interrupt { uint32_t flags; @@ -307,6 +331,12 @@ void igb_pf_mbx_process(struct rte_eth_dev *eth_dev); int igb_pf_host_configure(struct rte_eth_dev *eth_dev); +void igb_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_rxq_info *qinfo); + +void igb_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_txq_info *qinfo); + /* * RX/TX EM function prototypes */ @@ -343,6 +373,12 @@ uint16_t eth_em_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t eth_em_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +void em_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_rxq_info *qinfo); + +void em_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_txq_info *qinfo); + void igb_pf_host_uninit(struct rte_eth_dev *dev); #endif /* _E1000_ETHDEV_H_ */ diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c index 912f5dd..0cbc228 100644 --- a/drivers/net/e1000/em_ethdev.c +++ b/drivers/net/e1000/em_ethdev.c @@ -166,6 +166,8 @@ static const struct eth_dev_ops eth_em_ops = { .mac_addr_add = eth_em_rar_set, .mac_addr_remove = eth_em_rar_clear, .set_mc_addr_list = eth_em_set_mc_addr_list, + .rxq_info_get = em_rxq_info_get, + .txq_info_get = em_txq_info_get, }; /** @@ -933,6 +935,18 @@ eth_em_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) dev_info->max_rx_queues = 1; dev_info->max_tx_queues = 1; + + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = E1000_MAX_RING_DESC, + .nb_min = E1000_MIN_RING_DESC, + .nb_align = EM_RXD_ALIGN, + }; + + dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = E1000_MAX_RING_DESC, + .nb_min = E1000_MIN_RING_DESC, + .nb_align = EM_TXD_ALIGN, + }; } /* return 0 means link status changed, -1 means not changed */ diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c index 3b8776d..03e1bc2 100644 --- a/drivers/net/e1000/em_rxtx.c +++ b/drivers/net/e1000/em_rxtx.c @@ -1081,26 +1081,6 @@ eth_em_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, return (nb_rx); } -/* - * Rings setup and release. - * - * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be - * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. - * This will also optimize cache line size effect. - * H/W supports up to cache line size 128. - */ -#define EM_ALIGN 128 - -/* - * Maximum number of Ring Descriptors. - * - * Since RDLEN/TDLEN should be multiple of 128 bytes, the number of ring - * desscriptors should meet the following condition: - * (num_ring_desc * sizeof(struct e1000_rx/tx_desc)) % 128 == 0 - */ -#define EM_MIN_RING_DESC 32 -#define EM_MAX_RING_DESC 4096 - #defineEM_MAX_BUF_SIZE 16384 #define EM_RCTL_FLXBUF_STEP 1024 @@ -1210,11 +1190,11 @@ eth_em_tx_queue_setup(struct rte_eth_dev *dev, /* * Validate number of transmit descriptors. * It must not exceed hardware maximum, and must be multiple -*
[dpdk-dev] [PATCHv6 8/9] testpmd: add new command to display RX/TX queue information
From: "Ananyev, Konstantin" Signed-off-by: Konstantin Ananyev --- app/test-pmd/cmdline.c | 48 +++ app/test-pmd/config.c | 77 ++ app/test-pmd/testpmd.h | 2 ++ 3 files changed, 127 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0f8f48f..ea2b8a8 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -5305,6 +5305,53 @@ cmdline_parse_inst_t cmd_showport = { }, }; +/* *** SHOW QUEUE INFO *** */ +struct cmd_showqueue_result { + cmdline_fixed_string_t show; + cmdline_fixed_string_t type; + cmdline_fixed_string_t what; + uint8_t portnum; + uint16_t queuenum; +}; + +static void +cmd_showqueue_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_showqueue_result *res = parsed_result; + + if (!strcmp(res->type, "rxq")) + rx_queue_infos_display(res->portnum, res->queuenum); + else if (!strcmp(res->type, "txq")) + tx_queue_infos_display(res->portnum, res->queuenum); +} + +cmdline_parse_token_string_t cmd_showqueue_show = + TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, show, "show"); +cmdline_parse_token_string_t cmd_showqueue_type = + TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, type, "rxq#txq"); +cmdline_parse_token_string_t cmd_showqueue_what = + TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, what, "info"); +cmdline_parse_token_num_t cmd_showqueue_portnum = + TOKEN_NUM_INITIALIZER(struct cmd_showqueue_result, portnum, UINT8); +cmdline_parse_token_num_t cmd_showqueue_queuenum = + TOKEN_NUM_INITIALIZER(struct cmd_showqueue_result, queuenum, UINT16); + +cmdline_parse_inst_t cmd_showqueue = { + .f = cmd_showqueue_parsed, + .data = NULL, + .help_str = "show rxq|txq info ", + .tokens = { + (void *)&cmd_showqueue_show, + (void *)&cmd_showqueue_type, + (void *)&cmd_showqueue_what, + (void *)&cmd_showqueue_portnum, + (void *)&cmd_showqueue_queuenum, + NULL, + }, +}; + /* *** READ PORT REGISTER *** */ struct cmd_read_reg_result { cmdline_fixed_string_t read; @@ -8910,6 +8957,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, (cmdline_parse_inst_t *)&cmd_showport, + (cmdline_parse_inst_t *)&cmd_showqueue, (cmdline_parse_inst_t *)&cmd_showportall, (cmdline_parse_inst_t *)&cmd_showcfg, (cmdline_parse_inst_t *)&cmd_start, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index cf2aa6e..aad2ab6 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -293,6 +293,69 @@ nic_stats_mapping_display(portid_t port_id) } void +rx_queue_infos_display(portid_t port_id, uint16_t queue_id) +{ + struct rte_eth_rxq_info qinfo; + int32_t rc; + static const char *info_border = "*"; + + rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo); + if (rc != 0) { + printf("Failed to retrieve information for port: %hhu, " + "RX queue: %hu\nerror desc: %s(%d)\n", + port_id, queue_id, strerror(-rc), rc); + return; + } + + printf("\n%s Infos for port %-2u, RX queue %-2u %s", + info_border, port_id, queue_id, info_border); + + printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name); + printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh); + printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh); + printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh); + printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh); + printf("\nRX drop packets: %s", + (qinfo.conf.rx_drop_en != 0) ? "on" : "off"); + printf("\nRX deferred start: %s", + (qinfo.conf.rx_deferred_start != 0) ? "on" : "off"); + printf("\nRX scattered packets: %s", + (qinfo.scattered_rx != 0) ? "on" : "off"); + printf("\nNumber of RXDs: %hu", qinfo.nb_desc); + printf("\n"); +} + +void +tx_queue_infos_display(portid_t port_id, uint16_t queue_id) +{ + struct rte_eth_txq_info qinfo; + int32_t rc; + static const char *info_border = "*"; + + rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo); + if (rc != 0) { + printf("Failed to retrieve information for port: %hhu, " + "TX queue: %hu\nerror desc: %s(%d)\n", + port_id, queue_id, strerror(-rc), rc); + return; + } + + printf("\n%s Infos for port %-2u, TX queue %-2u %s", + info_border, port_i
[dpdk-dev] [PATCHv6 9/9] doc: release notes update for queue_info_get()
Signed-off-by: Konstantin Ananyev --- doc/guides/rel_notes/release_2_2.rst | 7 +++ 1 file changed, 7 insertions(+) diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst index 4f75cff..33ea399 100644 --- a/doc/guides/rel_notes/release_2_2.rst +++ b/doc/guides/rel_notes/release_2_2.rst @@ -9,6 +9,11 @@ New Features * Added support for Jumbo Frames. * Optimize forwarding performance for Chelsio T5 40GbE cards. +* **Add new API into rte_ethdev to retrieve RX/TX queue information.** + + * Add the ability for the upper layer to query RX/TX queue information. + * Add into rte_eth_dev_info new fields to represent information about + RX/TX descriptors min/max/alig nnumbers per queue for the device. Resolved Issues --- @@ -94,6 +99,8 @@ API Changes * The deprecated ring PMD functions are removed: rte_eth_ring_pair_create() and rte_eth_ring_pair_attach(). +* New functions rte_eth_rx_queue_info_get() and rte_eth_tx_queue_info_get() + are introduced. ABI Changes --- -- 1.8.5.3
[dpdk-dev] [PATCHv6 2/9] i40e: add support for eth_(rxq|txq)_info_get and (rx|tx)_desc_lim
This patch assumes that the patch: i40e: fix wrong alignment for the number of HW descriptors already applied. Signed-off-by: Konstantin Ananyev --- drivers/net/i40e/i40e_ethdev.c| 14 ++ drivers/net/i40e/i40e_ethdev.h| 5 + drivers/net/i40e/i40e_ethdev_vf.c | 12 drivers/net/i40e/i40e_rxtx.c | 37 + 4 files changed, 68 insertions(+) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 2dd9fdc..cbc1985 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -283,6 +283,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = { .udp_tunnel_add = i40e_dev_udp_tunnel_add, .udp_tunnel_del = i40e_dev_udp_tunnel_del, .filter_ctrl = i40e_dev_filter_ctrl, + .rxq_info_get = i40e_rxq_info_get, + .txq_info_get = i40e_txq_info_get, .mirror_rule_set = i40e_mirror_rule_set, .mirror_rule_reset= i40e_mirror_rule_reset, .timesync_enable = i40e_timesync_enable, @@ -1674,6 +1676,18 @@ i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) ETH_TXQ_FLAGS_NOOFFLOADS, }; + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = I40E_MAX_RING_DESC, + .nb_min = I40E_MIN_RING_DESC, + .nb_align = I40E_ALIGN_RING_DESC, + }; + + dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = I40E_MAX_RING_DESC, + .nb_min = I40E_MIN_RING_DESC, + .nb_align = I40E_ALIGN_RING_DESC, + }; + if (pf->flags & I40E_FLAG_VMDQ) { dev_info->max_vmdq_pools = pf->max_nb_vmdq_vsi; dev_info->vmdq_queue_base = dev_info->max_rx_queues; diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index 6185657..4748392 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -502,6 +502,11 @@ int i40e_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, void *arg); +void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_rxq_info *qinfo); +void i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_txq_info *qinfo); + /* I40E_DEV_PRIVATE_TO */ #define I40E_DEV_PRIVATE_TO_PF(adapter) \ (&((struct i40e_adapter *)adapter)->pf) diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c index b694400..5dad12d 100644 --- a/drivers/net/i40e/i40e_ethdev_vf.c +++ b/drivers/net/i40e/i40e_ethdev_vf.c @@ -1756,6 +1756,18 @@ i40evf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; + + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = I40E_MAX_RING_DESC, + .nb_min = I40E_MIN_RING_DESC, + .nb_align = I40E_ALIGN_RING_DESC, + }; + + dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = I40E_MAX_RING_DESC, + .nb_min = I40E_MIN_RING_DESC, + .nb_align = I40E_ALIGN_RING_DESC, + }; } static void diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c index 260e580..fa1451e 100644 --- a/drivers/net/i40e/i40e_rxtx.c +++ b/drivers/net/i40e/i40e_rxtx.c @@ -3063,3 +3063,40 @@ i40e_fdir_setup_rx_resources(struct i40e_pf *pf) return I40E_SUCCESS; } + +void +i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_rxq_info *qinfo) +{ + struct i40e_rx_queue *rxq; + + rxq = dev->data->rx_queues[queue_id]; + + qinfo->mp = rxq->mp; + qinfo->scattered_rx = dev->data->scattered_rx; + qinfo->nb_desc = rxq->nb_rx_desc; + + qinfo->conf.rx_free_thresh = rxq->rx_free_thresh; + qinfo->conf.rx_drop_en = rxq->drop_en; + qinfo->conf.rx_deferred_start = rxq->rx_deferred_start; +} + +void +i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_txq_info *qinfo) +{ + struct i40e_tx_queue *txq; + + txq = dev->data->tx_queues[queue_id]; + + qinfo->nb_desc = txq->nb_tx_desc; + + qinfo->conf.tx_thresh.pthresh = txq->pthresh; + qinfo->conf.tx_thresh.hthresh = txq->hthresh; + qinfo->conf.tx_thresh.wthresh = txq->wthresh; + + qinfo->conf.tx_free_thresh = txq->tx_free_thresh; + qinfo->conf.tx_rs_thresh = txq->tx_rs_thresh; + qinfo->conf.txq_flags = txq->txq_flags; + qinfo->conf.tx_deferred_start = txq->tx_deferred_start; +} -- 1.8.5.3
[dpdk-dev] [PATCHv6 5/9] fm10k: add HW specific desc_lim data into dev_info
Signed-off-by: Konstantin Ananyev --- drivers/net/fm10k/fm10k_ethdev.c | 11 +++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c index a69c990..9588dab 100644 --- a/drivers/net/fm10k/fm10k_ethdev.c +++ b/drivers/net/fm10k/fm10k_ethdev.c @@ -964,6 +964,17 @@ fm10k_dev_infos_get(struct rte_eth_dev *dev, ETH_TXQ_FLAGS_NOOFFLOADS, }; + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = FM10K_MAX_RX_DESC, + .nb_min = FM10K_MIN_RX_DESC, + .nb_align = FM10K_MULT_RX_DESC, + }; + + dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = FM10K_MAX_TX_DESC, + .nb_min = FM10K_MIN_TX_DESC, + .nb_align = FM10K_MULT_TX_DESC, + }; } static int -- 1.8.5.3
[dpdk-dev] [PATCHv6 7/9] vmxnet3: add HW specific desc_lim data into dev_info
Signed-off-by: Konstantin Ananyev --- drivers/net/vmxnet3/vmxnet3_ethdev.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c index a70be5c..3745b7d 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethdev.c +++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c @@ -677,6 +677,18 @@ vmxnet3_dev_info_get(__attribute__((unused))struct rte_eth_dev *dev, struct rte_ dev_info->default_txconf.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS; dev_info->flow_type_rss_offloads = VMXNET3_RSS_OFFLOAD_ALL; + + dev_info->rx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = VMXNET3_RX_RING_MAX_SIZE, + .nb_min = VMXNET3_DEF_RX_RING_SIZE, + .nb_align = 1, + }; + + dev_info->tx_desc_lim = (struct rte_eth_desc_lim) { + .nb_max = VMXNET3_TX_RING_MAX_SIZE, + .nb_min = VMXNET3_DEF_TX_RING_SIZE, + .nb_align = 1, + }; } /* return 0 means link status changed, -1 means not changed */ -- 1.8.5.3
[dpdk-dev] [PATCHv6 3/9] ixgbe: add support for eth_(rxq|txq)_info_get and (rx|tx)_desc_lim
Signed-off-by: Konstantin Ananyev --- drivers/net/ixgbe/ixgbe_ethdev.c | 23 ++ drivers/net/ixgbe/ixgbe_ethdev.h | 6 drivers/net/ixgbe/ixgbe_rxtx.c | 68 +--- drivers/net/ixgbe/ixgbe_rxtx.h | 21 + 4 files changed, 93 insertions(+), 25 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index ec2918c..4769bb0 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -386,6 +386,18 @@ static const struct rte_pci_id pci_id_ixgbevf_map[] = { }; +static const struct rte_eth_desc_lim rx_desc_lim = { + .nb_max = IXGBE_MAX_RING_DESC, + .nb_min = IXGBE_MIN_RING_DESC, + .nb_align = IXGBE_RXD_ALIGN, +}; + +static const struct rte_eth_desc_lim tx_desc_lim = { + .nb_max = IXGBE_MAX_RING_DESC, + .nb_min = IXGBE_MIN_RING_DESC, + .nb_align = IXGBE_TXD_ALIGN, +}; + static const struct eth_dev_ops ixgbe_eth_dev_ops = { .dev_configure= ixgbe_dev_configure, .dev_start= ixgbe_dev_start, @@ -456,6 +468,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = { .rss_hash_conf_get= ixgbe_dev_rss_hash_conf_get, .filter_ctrl = ixgbe_dev_filter_ctrl, .set_mc_addr_list = ixgbe_dev_set_mc_addr_list, + .rxq_info_get = ixgbe_rxq_info_get, + .txq_info_get = ixgbe_txq_info_get, .timesync_enable = ixgbe_timesync_enable, .timesync_disable = ixgbe_timesync_disable, .timesync_read_rx_timestamp = ixgbe_timesync_read_rx_timestamp, @@ -494,6 +508,8 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = { .mac_addr_add = ixgbevf_add_mac_addr, .mac_addr_remove = ixgbevf_remove_mac_addr, .set_mc_addr_list = ixgbe_dev_set_mc_addr_list, + .rxq_info_get = ixgbe_rxq_info_get, + .txq_info_get = ixgbe_txq_info_get, .mac_addr_set = ixgbevf_set_default_mac_addr, .get_reg_length = ixgbevf_get_reg_length, .get_reg = ixgbevf_get_regs, @@ -2396,6 +2412,10 @@ ixgbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; + + dev_info->rx_desc_lim = rx_desc_lim; + dev_info->tx_desc_lim = tx_desc_lim; + dev_info->hash_key_size = IXGBE_HKEY_MAX_INDEX * sizeof(uint32_t); dev_info->reta_size = ETH_RSS_RETA_SIZE_128; dev_info->flow_type_rss_offloads = IXGBE_RSS_OFFLOAD_ALL; @@ -2449,6 +2469,9 @@ ixgbevf_dev_info_get(struct rte_eth_dev *dev, .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS | ETH_TXQ_FLAGS_NOOFFLOADS, }; + + dev_info->rx_desc_lim = rx_desc_lim; + dev_info->tx_desc_lim = tx_desc_lim; } /* return 0 means link status changed, -1 means not changed */ diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h index c3d4f4f..d16f476 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.h +++ b/drivers/net/ixgbe/ixgbe_ethdev.h @@ -351,6 +351,12 @@ int ixgbe_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id); int ixgbe_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id); +void ixgbe_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_rxq_info *qinfo); + +void ixgbe_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id, + struct rte_eth_txq_info *qinfo); + int ixgbevf_dev_rx_init(struct rte_eth_dev *dev); void ixgbevf_dev_tx_init(struct rte_eth_dev *dev); diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c index a598a72..ba08588 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx.c +++ b/drivers/net/ixgbe/ixgbe_rxtx.c @@ -1821,25 +1821,6 @@ ixgbe_recv_pkts_lro_bulk_alloc(void *rx_queue, struct rte_mbuf **rx_pkts, **/ /* - * Rings setup and release. - * - * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be - * multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will - * also optimize cache line size effect. H/W supports up to cache line size 128. - */ -#define IXGBE_ALIGN 128 - -/* - * Maximum number of Ring Descriptors. - * - * Since RDLEN/TDLEN should be multiple of 128 bytes, the number of ring - * descriptors should meet the following condition: - * (num_ring_desc * sizeof(rx/tx descriptor)) % 128 == 0 - */ -#define IXGBE_MIN_RING_DESC 32 -#define IXGBE_MAX_RING_DESC 4096 - -/* * Create memzone for HW rings. malloc can't be used as the physical address is * needed. If the memzone is already created, then this function returns a ptr * to the old one. @@ -2007,9 +1988,9 @@ ixgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, * It must not exceed hardware maxi
[dpdk-dev] [PATCH v4 0/7] virtio ring layout optimization and simple rx/tx processing
Changes in v2: - Remove the configure macro - Enable simple R/TX processing when user specifies simple txq flags - Reword some comments and commit messages Changes in v3: - Remove unnecessary NULL test for rte_free - Remove unnecessary assign of local var after free - Remove return at the end of void function - Remove always_inline attribute for virtio_xmit_cleanup - Reword some commit messages - Add TODO in the commit message of simple tx patch Changes in v4: - Fix the error in virtio tx ring layout ascii chart in the commit message - move virtio_xmit_cleanup ahead to free descriptors earlier - Test merge-able feature when select simple rx/tx functions In DPDK based switching enviroment, mostly vhost runs on a dedicated core while virtio processing in guest VMs runs on other different cores. Take RX for example, with generic implementation, for each guest buffer, a) virtio driver allocates a descriptor from free descriptor list b) modify the entry of avail ring to point to allocated descriptor c) after packet is received, free the descriptor When vhost fetches the avail ring, it need to fetch the modified L1 cache from virtio core, which is a heavy cost in current CPU implementation. This idea of this optimization is: allocate the fixed descriptor for each entry of avail ring, so avail ring will always be the same during the run. This removes L1M cache transfer from virtio core to vhost core for avail ring. (Note we couldn't avoid the cache transfer for descriptors). Besides, descriptor allocation and free operation is eliminated. This also makes vector procesing possible to further accelerate the processing. This is the layout for the avail ring(take 256 ring entries for example), with each entry pointing to the descriptor with the same index. avail idx + | +++---+-+--+ | 0 | 1 | 2 | ... | 254 | 255 | avail ring +-+--+-+--+-+-+-+---+--+---+ ||| | | | ||| | | | vvv | v v +-+--+-+--+-+-+-+---+--+---+ | 0 | 1 | 2 | ... | 254 | 255 | desc ring +++---+-+--+ | | +++---+-+--+ | 0 | 1 | 2 | | 254 | 255 | used ring +++---+-+--+ | + This is the ring layout for TX. As we need one virtio header for each xmit packet, we have 128 slots available. ++ || || +-+-+-+--+--+--+--+ | 0 | 1 | ... | 127 || 128 | 129 | ... | 255 | avail ring +--+--+--+--+-+---+--+---+--+---+--+--+---+ | || || | | | v vv || v v v +--+--+--+--+-+---+--+---+--+---+--+--+---+ | 127 | 128 | ... | 255 || 127 | 128 | ... | 255 | desc ring for virtio_net_hdr +--+--+--+--+-+---+--+---+--+---+--+--+---+ | || || | | | v vv || v v v +--+--+--+--+-+---+--+---+--+---+--+--+---+ | 0 | 1 | ... | 127 || 0 | 1 | ... | 127 | desc ring for tx dat +-+-+-+--+--+--+--+ || || ++ Performance boost could be observed only if the virtio backend isn't the bottleneck or in VM2VM case. There are also several vhost optimization patches to be submitted later. Huawei Xie (7): virtio: add virtio_rxtx.h header file virtio: add software rx ring, fake_buf into virtqueue virtio: rx/tx ring layout optimization virtio: fill RX avail ring with blank mbufs virtio: virtio vec rx virtio: simple tx routine virtio: choose simple rx/tx func drivers/net/virtio/Makefile | 2 +- drivers/net/virtio/virtio_ethdev.c | 12 +- drivers/net/virtio/virtio_ethdev.h | 5 + drivers/net/virtio/virtio_rxtx.c| 56 - drivers/net/virtio/virtio_rxtx.h| 39 drivers/net/virtio/virtio_rxtx_simple.c | 401 drivers/net/virtio/virtqueue.h | 5 + 7 files changed, 516 insertions(+), 4 deletions(-) create mode 100644 drivers/net/virtio/virtio_rxtx.h create mode 100644 drivers/net/virtio/virtio_rxtx_simple.c -- 1.8.1.4
[dpdk-dev] [PATCH v4 1/7] virtio: add virtio_rxtx.h header file
Would move all rx/tx related declarations into this header file in future. Add RTE_VIRTIO_PMD_MAX_BURST. Signed-off-by: Huawei Xie --- drivers/net/virtio/virtio_ethdev.c | 1 + drivers/net/virtio/virtio_rxtx.c | 1 + drivers/net/virtio/virtio_rxtx.h | 34 ++ 3 files changed, 36 insertions(+) create mode 100644 drivers/net/virtio/virtio_rxtx.h diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 465d3cd..79a3640 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -61,6 +61,7 @@ #include "virtio_pci.h" #include "virtio_logs.h" #include "virtqueue.h" +#include "virtio_rxtx.h" static int eth_virtio_dev_init(struct rte_eth_dev *eth_dev); diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index c5b53bb..9324f7f 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -54,6 +54,7 @@ #include "virtio_logs.h" #include "virtio_ethdev.h" #include "virtqueue.h" +#include "virtio_rxtx.h" #ifdef RTE_LIBRTE_VIRTIO_DEBUG_DUMP #define VIRTIO_DUMP_PACKET(m, len) rte_pktmbuf_dump(stdout, m, len) diff --git a/drivers/net/virtio/virtio_rxtx.h b/drivers/net/virtio/virtio_rxtx.h new file mode 100644 index 000..a10aa69 --- /dev/null +++ b/drivers/net/virtio/virtio_rxtx.h @@ -0,0 +1,34 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2015 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. + */ + +#define RTE_PMD_VIRTIO_RX_MAX_BURST 64 -- 1.8.1.4
[dpdk-dev] [PATCH v4 3/7] virtio: rx/tx ring layout optimization
Changes in V4: - fix the error in tx ring layout chart in this commit message. In DPDK based switching envrioment, mostly vhost runs on a dedicated core while virtio processing in guest VMs runs on different cores. Take RX for example, with generic implementation, for each guest buffer, a) virtio driver allocates a descriptor from free descriptor list b) modify the entry of avail ring to point to allocated descriptor c) after packet is received, free the descriptor When vhost fetches the avail ring, it need to fetch the modified L1 cache from virtio core, which is a heavy cost in current CPU implementation. This idea of this optimization is: allocate the fixed descriptor for each entry of avail ring, so avail ring will always be the same during the run. This removes L1M cache transfer from virtio core to vhost core for avail ring. (Note we couldn't avoid the cache transfer for descriptors). Besides, descriptor allocation and free operation is eliminated. This also makes vector procesing possible to further accelerate the processing. This is the layout for the avail ring(take 256 ring entries for example), with each entry pointing to the descriptor with the same index. avail idx + | +++---+-+--+ | 0 | 1 | 2 | ... | 254 | 255 | avail ring +-+--+-+--+-+-+-+---+--+---+ ||| | | | ||| | | | vvv | v v +-+--+-+--+-+-+-+---+--+---+ | 0 | 1 | 2 | ... | 254 | 255 | desc ring +++---+-+--+ | | +++---+-+--+ | 0 | 1 | 2 | | 254 | 255 | used ring +++---+-+--+ | + This is the ring layout for TX. As we need one virtio header for each xmit packet, we have 128 slots available. ++ || || +-+-+-+--+--+--+--+ | 0 | 1 | ... | 127 || 128 | 129 | ... | 255 | avail ring +--+--+--+--+-+---+--+---+--+---+--+--+---+ | || || | | | v vv || v v v +--+--+--+--+-+---+--+---+--+---+--+--+---+ | 128 | 129 | ... | 255 || 128 | 129 | ... | 255 | desc ring for virtio_net_hdr +--+--+--+--+-+---+--+---+--+---+--+--+---+ | || || | | | v vv || v v v +--+--+--+--+-+---+--+---+--+---+--+--+---+ | 0 | 1 | ... | 127 || 0 | 1 | ... | 127 | desc ring for tx dat +-+-+-+--+--+--+--+ || || ++ Signed-off-by: Huawei Xie --- drivers/net/virtio/virtio_rxtx.c | 24 1 file changed, 24 insertions(+) diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 5c00e9d..7c82a6a 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -302,6 +302,12 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) nbufs = 0; error = ENOSPC; + if (use_simple_rxtx) + for (i = 0; i < vq->vq_nentries; i++) { + vq->vq_ring.avail->ring[i] = i; + vq->vq_ring.desc[i].flags = VRING_DESC_F_WRITE; + } + memset(&vq->fake_mbuf, 0, sizeof(vq->fake_mbuf)); for (i = 0; i < RTE_PMD_VIRTIO_RX_MAX_BURST; i++) vq->sw_ring[vq->vq_nentries + i] = &vq->fake_mbuf; @@ -332,6 +338,24 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) VIRTIO_WRITE_REG_4(vq->hw, VIRTIO_PCI_QUEUE_PFN, vq->mz->phys_addr >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); } else if (queue_type == VTNET_TQ) { + if (use_simple_rxtx) { + int mid_idx = vq->vq_nentries >> 1; + for (i = 0; i < mid_idx; i++) { + vq->vq_ring.avail->ring[i] = i + mid_idx; + vq->vq_ring.desc[i + mid_idx].next = i; + vq->vq_ring.desc[i + mid_idx].addr = + vq->virtio_net_hdr_mem + + mid_idx * vq->hw->vtnet_hdr_size; + vq->vq_ring.desc[i + mid_idx].len = + vq->hw->vtnet_hdr_size; + vq->vq_ring.desc[i + mid_idx].flags = + VRING_DESC_F_NEXT; + vq->vq_ring.desc[i].flags = 0; + } +
[dpdk-dev] [PATCH v4 2/7] virtio: add software rx ring, fake_buf into virtqueue
Changes in v3: - Remove unnecessary NULL test for rte_free - Remove unnecessary assign of local var vq after free Add software RX ring in virtqueue. Add fake_mbuf in virtqueue for wraparound processing. Use global simple_rxtx to indicate whether simple rxtx is enabled Signed-off-by: Huawei Xie --- drivers/net/virtio/virtio_ethdev.c | 11 ++- drivers/net/virtio/virtio_rxtx.c | 7 +++ drivers/net/virtio/virtqueue.h | 4 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 79a3640..82676d3 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -247,8 +247,8 @@ virtio_dev_queue_release(struct virtqueue *vq) { VIRTIO_WRITE_REG_2(hw, VIRTIO_PCI_QUEUE_SEL, vq->queue_id); VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_QUEUE_PFN, 0); + rte_free(vq->sw_ring); rte_free(vq); - vq = NULL; } } @@ -292,6 +292,9 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, dev->data->port_id, queue_idx); vq = rte_zmalloc(vq_name, sizeof(struct virtqueue) + vq_size * sizeof(struct vq_desc_extra), RTE_CACHE_LINE_SIZE); + vq->sw_ring = rte_zmalloc_socket("rxq->sw_ring", + (RTE_PMD_VIRTIO_RX_MAX_BURST + vq_size) * + sizeof(vq->sw_ring[0]), RTE_CACHE_LINE_SIZE, socket_id); } else if (queue_type == VTNET_TQ) { snprintf(vq_name, sizeof(vq_name), "port%d_tvq%d", dev->data->port_id, queue_idx); @@ -308,6 +311,12 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev, PMD_INIT_LOG(ERR, "%s: Can not allocate virtqueue", __func__); return (-ENOMEM); } + if (queue_type == VTNET_RQ && vq->sw_ring == NULL) { + PMD_INIT_LOG(ERR, "%s: Can not allocate RX soft ring", + __func__); + rte_free(vq); + return -ENOMEM; + } vq->hw = hw; vq->port_id = dev->data->port_id; diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 9324f7f..5c00e9d 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -62,6 +62,8 @@ #define VIRTIO_DUMP_PACKET(m, len) do { } while (0) #endif +static int use_simple_rxtx; + static void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) { @@ -299,6 +301,11 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) /* Allocate blank mbufs for the each rx descriptor */ nbufs = 0; error = ENOSPC; + + memset(&vq->fake_mbuf, 0, sizeof(vq->fake_mbuf)); + for (i = 0; i < RTE_PMD_VIRTIO_RX_MAX_BURST; i++) + vq->sw_ring[vq->vq_nentries + i] = &vq->fake_mbuf; + while (!virtqueue_full(vq)) { m = rte_rxmbuf_alloc(vq->mpool); if (m == NULL) diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h index 7789411..6a1ec48 100644 --- a/drivers/net/virtio/virtqueue.h +++ b/drivers/net/virtio/virtqueue.h @@ -190,6 +190,10 @@ struct virtqueue { uint16_t vq_avail_idx; phys_addr_t virtio_net_hdr_mem; /**< hdr for each xmit packet */ + struct rte_mbuf **sw_ring; /**< RX software ring. */ + /* dummy mbuf, for wraparound when processing RX ring. */ + struct rte_mbuf fake_mbuf; + /* Statistics */ uint64_tpackets; uint64_tbytes; -- 1.8.1.4
[dpdk-dev] [PATCH v4 4/7] virtio: fill RX avail ring with blank mbufs
fill avail ring with blank mbufs in virtio_dev_vring_start Signed-off-by: Huawei Xie --- drivers/net/virtio/Makefile | 2 +- drivers/net/virtio/virtio_rxtx.c| 6 ++- drivers/net/virtio/virtio_rxtx.h| 3 ++ drivers/net/virtio/virtio_rxtx_simple.c | 84 + 4 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 drivers/net/virtio/virtio_rxtx_simple.c diff --git a/drivers/net/virtio/Makefile b/drivers/net/virtio/Makefile index 930b60f..43835ba 100644 --- a/drivers/net/virtio/Makefile +++ b/drivers/net/virtio/Makefile @@ -50,7 +50,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtqueue.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_pci.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_ethdev.c - +SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_rxtx_simple.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += lib/librte_eal lib/librte_ether diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 7c82a6a..5162ce6 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -320,8 +320,10 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type) /** * Enqueue allocated buffers* ***/ - error = virtqueue_enqueue_recv_refill(vq, m); - + if (use_simple_rxtx) + error = virtqueue_enqueue_recv_refill_simple(vq, m); + else + error = virtqueue_enqueue_recv_refill(vq, m); if (error) { rte_pktmbuf_free(m); break; diff --git a/drivers/net/virtio/virtio_rxtx.h b/drivers/net/virtio/virtio_rxtx.h index a10aa69..7d2d8fe 100644 --- a/drivers/net/virtio/virtio_rxtx.h +++ b/drivers/net/virtio/virtio_rxtx.h @@ -32,3 +32,6 @@ */ #define RTE_PMD_VIRTIO_RX_MAX_BURST 64 + +int virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, + struct rte_mbuf *m); diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c new file mode 100644 index 000..cac5b9f --- /dev/null +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -0,0 +1,84 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2015 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 +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virtio_logs.h" +#include "virtio_ethdev.h" +#include "virtqueue.h" +#include "virtio_rxtx.h" + +int __attribute__((cold)) +virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, + struct rte_mbuf *cookie) +{ + struct vq_desc_extra *dxp; + struct vring_desc *start_dp; + uint16_t desc_idx; + + desc_idx = vq->vq_avail_idx & (vq->vq_nentries - 1); + dxp = &vq->vq_descx[desc_idx]; + dxp->cookie = (void *)cookie; + vq->sw_ring[desc_idx] = cookie; + + start_dp = vq->vq_ring.desc; + start_dp[desc_idx
[dpdk-dev] [PATCH v4 5/7] virtio: virtio vec rx
With fixed avail ring, we don't need to get desc idx from avail ring. virtio driver only has to deal with desc ring. This patch uses vector instruction to accelerate processing desc ring. Signed-off-by: Huawei Xie --- drivers/net/virtio/virtio_ethdev.h | 2 + drivers/net/virtio/virtio_rxtx.c| 3 + drivers/net/virtio/virtio_rxtx.h| 2 + drivers/net/virtio/virtio_rxtx_simple.c | 224 drivers/net/virtio/virtqueue.h | 1 + 5 files changed, 232 insertions(+) diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index 9026d42..d7797ab 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -108,6 +108,8 @@ uint16_t virtio_recv_mergeable_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); +uint16_t virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts); /* * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 5162ce6..947fc46 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -432,6 +432,9 @@ virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, vq->mpool = mp; dev->data->rx_queues[queue_idx] = vq; + + virtio_rxq_vec_setup(vq); + return 0; } diff --git a/drivers/net/virtio/virtio_rxtx.h b/drivers/net/virtio/virtio_rxtx.h index 7d2d8fe..831e492 100644 --- a/drivers/net/virtio/virtio_rxtx.h +++ b/drivers/net/virtio/virtio_rxtx.h @@ -33,5 +33,7 @@ #define RTE_PMD_VIRTIO_RX_MAX_BURST 64 +int virtio_rxq_vec_setup(struct virtqueue *rxq); + int virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, struct rte_mbuf *m); diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c index cac5b9f..ef17562 100644 --- a/drivers/net/virtio/virtio_rxtx_simple.c +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -58,6 +58,10 @@ #include "virtqueue.h" #include "virtio_rxtx.h" +#define RTE_VIRTIO_VPMD_RX_BURST 32 +#define RTE_VIRTIO_DESC_PER_LOOP 8 +#define RTE_VIRTIO_VPMD_RX_REARM_THRESH RTE_VIRTIO_VPMD_RX_BURST + int __attribute__((cold)) virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, struct rte_mbuf *cookie) @@ -82,3 +86,223 @@ virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq, return 0; } + +static inline void +virtio_rxq_rearm_vec(struct virtqueue *rxvq) +{ + int i; + uint16_t desc_idx; + struct rte_mbuf **sw_ring; + struct vring_desc *start_dp; + int ret; + + desc_idx = rxvq->vq_avail_idx & (rxvq->vq_nentries - 1); + sw_ring = &rxvq->sw_ring[desc_idx]; + start_dp = &rxvq->vq_ring.desc[desc_idx]; + + ret = rte_mempool_get_bulk(rxvq->mpool, (void **)sw_ring, + RTE_VIRTIO_VPMD_RX_REARM_THRESH); + if (unlikely(ret)) { + rte_eth_devices[rxvq->port_id].data->rx_mbuf_alloc_failed += + RTE_VIRTIO_VPMD_RX_REARM_THRESH; + return; + } + + for (i = 0; i < RTE_VIRTIO_VPMD_RX_REARM_THRESH; i++) { + uintptr_t p; + + p = (uintptr_t)&sw_ring[i]->rearm_data; + *(uint64_t *)p = rxvq->mbuf_initializer; + + start_dp[i].addr = + (uint64_t)((uintptr_t)sw_ring[i]->buf_physaddr + + RTE_PKTMBUF_HEADROOM - sizeof(struct virtio_net_hdr)); + start_dp[i].len = sw_ring[i]->buf_len - + RTE_PKTMBUF_HEADROOM + sizeof(struct virtio_net_hdr); + } + + rxvq->vq_avail_idx += RTE_VIRTIO_VPMD_RX_REARM_THRESH; + rxvq->vq_free_cnt -= RTE_VIRTIO_VPMD_RX_REARM_THRESH; + vq_update_avail_idx(rxvq); +} + +/* virtio vPMD receive routine, only accept(nb_pkts >= RTE_VIRTIO_DESC_PER_LOOP) + * + * This routine is for non-mergable RX, one desc for each guest buffer. + * This routine is based on the RX ring layout optimization. Each entry in the + * avail ring points to the desc with the same index in the desc ring and this + * will never be changed in the driver. + * + * - nb_pkts < RTE_VIRTIO_DESC_PER_LOOP, just return no packet + */ +uint16_t +virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, + uint16_t nb_pkts) +{ + struct virtqueue *rxvq = rx_queue; + uint16_t nb_used; + uint16_t desc_idx; + struct vring_used_elem *rused; + struct rte_mbuf **sw_ring; + struct rte_mbuf **sw_ring_end; + uint16_t nb_pkts_received; + __m128i shuf_msk1, shuf_msk2, len_adjust; + + shuf_msk1 = _mm_set_epi8( + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, /* vlan tci */ + 5, 4, /* dat len */ + 0xFF, 0xFF, 5, 4,
[dpdk-dev] [PATCH v4 6/7] virtio: simple tx routine
Changes in v4: - move virtio_xmit_cleanup ahead to free descriptors earlier Changes in v3: - Remove return at the end of void function - Remove always_inline attribute for virtio_xmit_cleanup bulk free of mbufs when clean used ring. shift operation of idx could be saved if vq_free_cnt means free slots rather than free descriptors. TODO: rearrange vq data structure, pack the stats var together so that we could use one vec instruction to update all of them. Signed-off-by: Huawei Xie --- drivers/net/virtio/virtio_ethdev.h | 3 ++ drivers/net/virtio/virtio_rxtx_simple.c | 93 + 2 files changed, 96 insertions(+) diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index d7797ab..ae2d47d 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -111,6 +111,9 @@ uint16_t virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts); + /* * The VIRTIO_NET_F_GUEST_TSO[46] features permit the host to send us * frames larger than 1514 bytes. We do not yet support software LRO diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c index ef17562..79b4f7f 100644 --- a/drivers/net/virtio/virtio_rxtx_simple.c +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -288,6 +288,99 @@ virtio_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts, return nb_pkts_received; } +#define VIRTIO_TX_FREE_THRESH 32 +#define VIRTIO_TX_MAX_FREE_BUF_SZ 32 +#define VIRTIO_TX_FREE_NR 32 +/* TODO: vq->tx_free_cnt could mean num of free slots so we could avoid shift */ +static inline void +virtio_xmit_cleanup(struct virtqueue *vq) +{ + uint16_t i, desc_idx; + int nb_free = 0; + struct rte_mbuf *m, *free[VIRTIO_TX_MAX_FREE_BUF_SZ]; + + desc_idx = (uint16_t)(vq->vq_used_cons_idx & + ((vq->vq_nentries >> 1) - 1)); + free[0] = (struct rte_mbuf *)vq->vq_descx[desc_idx++].cookie; + nb_free = 1; + + for (i = 1; i < VIRTIO_TX_FREE_NR; i++) { + m = (struct rte_mbuf *)vq->vq_descx[desc_idx++].cookie; + if (likely(m->pool == free[0]->pool)) + free[nb_free++] = m; + else { + rte_mempool_put_bulk(free[0]->pool, (void **)free, + nb_free); + free[0] = m; + nb_free = 1; + } + } + + rte_mempool_put_bulk(free[0]->pool, (void **)free, nb_free); + vq->vq_used_cons_idx += VIRTIO_TX_FREE_NR; + vq->vq_free_cnt += (VIRTIO_TX_FREE_NR << 1); +} + +uint16_t +virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, + uint16_t nb_pkts) +{ + struct virtqueue *txvq = tx_queue; + uint16_t nb_used; + uint16_t desc_idx; + struct vring_desc *start_dp; + uint16_t nb_tail, nb_commit; + int i; + uint16_t desc_idx_max = (txvq->vq_nentries >> 1) - 1; + + nb_used = VIRTQUEUE_NUSED(txvq); + rte_compiler_barrier(); + + if (nb_used >= VIRTIO_TX_FREE_THRESH) + virtio_xmit_cleanup(tx_queue); + + nb_commit = nb_pkts = RTE_MIN((txvq->vq_free_cnt >> 1), nb_pkts); + desc_idx = (uint16_t) (txvq->vq_avail_idx & desc_idx_max); + start_dp = txvq->vq_ring.desc; + nb_tail = (uint16_t) (desc_idx_max + 1 - desc_idx); + + if (nb_commit >= nb_tail) { + for (i = 0; i < nb_tail; i++) + txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i]; + for (i = 0; i < nb_tail; i++) { + start_dp[desc_idx].addr = + RTE_MBUF_DATA_DMA_ADDR(*tx_pkts); + start_dp[desc_idx].len = (*tx_pkts)->pkt_len; + tx_pkts++; + desc_idx++; + } + nb_commit -= nb_tail; + desc_idx = 0; + } + for (i = 0; i < nb_commit; i++) + txvq->vq_descx[desc_idx + i].cookie = tx_pkts[i]; + for (i = 0; i < nb_commit; i++) { + start_dp[desc_idx].addr = RTE_MBUF_DATA_DMA_ADDR(*tx_pkts); + start_dp[desc_idx].len = (*tx_pkts)->pkt_len; + tx_pkts++; + desc_idx++; + } + + rte_compiler_barrier(); + + txvq->vq_free_cnt -= (uint16_t)(nb_pkts << 1); + txvq->vq_avail_idx += nb_pkts; + txvq->vq_ring.avail->idx = txvq->vq_avail_idx; + txvq->packets += nb_pkts; + + if (likely(nb_pkts)) { + if (unlikely(virtqueue_kick_prepare(txvq))) + virtqueue_notify(txvq); + } + + return nb_pkts; +} + int __attribute__((cold)) virtio_rxq_vec_setup(struct vir
[dpdk-dev] [PATCH v4 7/7] virtio: pick simple rx/tx func
Changes in v4: Check merge-able feature when select simple rx/tx functions. simple rx/tx func is chose when merge-able rx is disabled and user specifies single segment and no offload support. Signed-off-by: Huawei Xie --- drivers/net/virtio/virtio_rxtx.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 947fc46..0f1daf2 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -53,6 +53,7 @@ #include "virtio_logs.h" #include "virtio_ethdev.h" +#include "virtio_pci.h" #include "virtqueue.h" #include "virtio_rxtx.h" @@ -62,6 +63,10 @@ #define VIRTIO_DUMP_PACKET(m, len) do { } while (0) #endif + +#define VIRTIO_SIMPLE_FLAGS ((uint32_t)ETH_TXQ_FLAGS_NOMULTSEGS | \ + ETH_TXQ_FLAGS_NOOFFLOADS) + static int use_simple_rxtx; static void @@ -459,6 +464,7 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, const struct rte_eth_txconf *tx_conf) { uint8_t vtpci_queue_idx = 2 * queue_idx + VTNET_SQ_TQ_QUEUE_IDX; + struct virtio_hw *hw = dev->data->dev_private; struct virtqueue *vq; uint16_t tx_free_thresh; int ret; @@ -471,6 +477,15 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev, return -EINVAL; } + /* Use simple rx/tx func if single segment and no offloads */ + if ((tx_conf->txq_flags & VIRTIO_SIMPLE_FLAGS) == VIRTIO_SIMPLE_FLAGS && +!vtpci_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) { + PMD_INIT_LOG(INFO, "Using simple rx/tx path"); + dev->tx_pkt_burst = virtio_xmit_pkts_simple; + dev->rx_pkt_burst = virtio_recv_pkts_vec; + use_simple_rxtx = 1; + } + ret = virtio_dev_queue_setup(dev, VTNET_TQ, queue_idx, vtpci_queue_idx, nb_desc, socket_id, &vq); if (ret < 0) { -- 1.8.1.4
[dpdk-dev] [PATCH v2 0/5] virtio: Tx performance improvements
On 10/22/2015 6:39 PM, Xie, Huawei wrote: > On 10/21/2015 9:20 PM, Thomas Monjalon wrote: >> 2015-10-18 22:16, Stephen Hemminger: >>> This is a tested version of the virtio Tx performance improvements >>> that I posted earlier on the list, and described at the DPDK Userspace >>> meeting in Dublin. Together they get a 25% performance improvement for >>> both small packet and large multi-segment packet case when testing >>> from DPDK guest application to Linux KVM host. >>> >>> Stephen Hemminger (5): >>> virtio: clean up space checks on xmit >>> virtio: don't use unlikely for normal tx stuff >>> virtio: use indirect ring elements >>> virtio: use any layout on transmit >>> virtio: optimize transmit enqueue >> Huawei, do you ack this series? >> > Okay with this patchset with two remained questions, Forget to cc Stephen. > > +/* Region reserved to allow for transmit header and indirect ring */ > +#define VIRTIO_MAX_TX_INDIRECT 8 > +struct virtio_tx_region { > + struct virtio_net_hdr_mrg_rxbuf tx_hdr; > > Why use merge-able rx header here in the tx region? > >> +struct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT] >> + __attribute__((__aligned__(16))); > WARNING: __aligned(size) is preferred over __attribute__((aligned(size))) > [...] > > > >
[dpdk-dev] [PATCH v8 0/8] vhost-user multiple queues enabling
This patch set enables vhost-user multiple queue feature. v8: - put SET_VRING_ENABLE() patch before the patch actually enable mq, since that make more sense. - don't change the kickfd reset behavior for patch 3 - move virt_queue field to the end of virtio_net struct. - comment and type fixe v7: - Removed vhost-user mq examples in this patch set Because the example leverages the hardware VMDq feature to demonstrate the mq feature, which introduces too much limitation, yet it's turned out to be not elegant. - Commit log fixes - Dropped the patch to fix RESET_OWNER handling, as I found Jerome's solution works as well, and it makes more sense to me: http://dpdk.org/dev/patchwork/project/dpdk/list/?submitter=354 Overview It depends on some QEMU patches that has already been merged to upstream. Those qemu patches introduce some new vhost-user messages, for vhost-user mq enabling negotiation. Here is the main negotiation steps (Qemu as master, and DPDK vhost-user as slave): - Master queries features by VHOST_USER_GET_FEATURES from slave - Check if VHOST_USER_F_PROTOCOL_FEATURES exist. If not, mq is not supported. (check patch 1 for why VHOST_USER_F_PROTOCOL_FEATURES is introduced) - Master then sends another command, VHOST_USER_GET_QUEUE_NUM, for querying how many queues the slave supports. Master will compare the result with the requested queue number. Qemu exits if the former is smaller. - Master then tries to initiate all queue pairs by sending some vhost user commands, including VHOST_USER_SET_VRING_CALL, which will trigger the slave to do related vring setup, such as vring allocation. Till now, all necessary initiation and negotiation are done. And master could send another message, VHOST_USER_SET_VRING_ENABLE, to enable/disable a specific queue dynamically later. Patchset Patch 1-6 are all prepare works for enabling mq; they are all atomic changes, with "do not breaking anything" beared in mind while making them. Patch 7 actually enables mq feature, by setting two key feature flags. Test with OVS = Marcel created a simple yet quite clear test guide with OVS at: http://wiki.qemu.org/Features/vhost-user-ovs-dpdk --- Changchun Ouyang (3): vhost: rxtx: use queue id instead of constant ring index virtio: fix deadloop due to reading virtio_net_config incorrectly vhost: add VHOST_USER_SET_VRING_ENABLE message Yuanhan Liu (5): vhost-user: add protocol features support vhost-user: add VHOST_USER_GET_QUEUE_NUM message vhost: vring queue setup for multiple queue support vhost-user: enable vhost-user multiple queue doc: update release note for vhost-user mq support doc/guides/rel_notes/release_2_2.rst | 4 + drivers/net/virtio/virtio_ethdev.c| 16 ++- lib/librte_vhost/rte_virtio_net.h | 13 +- lib/librte_vhost/vhost_rxtx.c | 53 +--- lib/librte_vhost/vhost_user/vhost-net-user.c | 25 +++- lib/librte_vhost/vhost_user/vhost-net-user.h | 4 + lib/librte_vhost/vhost_user/virtio-net-user.c | 86 ++--- lib/librte_vhost/vhost_user/virtio-net-user.h | 10 ++ lib/librte_vhost/virtio-net.c | 168 -- 9 files changed, 275 insertions(+), 104 deletions(-) -- 1.9.0
[dpdk-dev] [PATCH v8 1/8] vhost-user: add protocol features support
The two protocol features messages are introduced by qemu vhost maintainer(Michael) for extendting vhost-user interface. Here is an excerpta from the vhost-user spec: Any protocol extensions are gated by protocol feature bits, which allows full backwards compatibility on both master and slave. The vhost-user multiple queue features will be treated as a vhost-user extension, hence, we have to implement the two messages first. VHOST_USER_PROTOCOL_FEATURES is initialized to 0, as we don't support any yet. Signed-off-by: Yuanhan Liu Acked-by: Flavio Leitner --- lib/librte_vhost/rte_virtio_net.h | 1 + lib/librte_vhost/vhost_user/vhost-net-user.c | 13 - lib/librte_vhost/vhost_user/vhost-net-user.h | 2 ++ lib/librte_vhost/vhost_user/virtio-net-user.c | 13 + lib/librte_vhost/vhost_user/virtio-net-user.h | 5 + lib/librte_vhost/virtio-net.c | 5 - 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index a037c15..e3a21e5 100644 --- a/lib/librte_vhost/rte_virtio_net.h +++ b/lib/librte_vhost/rte_virtio_net.h @@ -99,6 +99,7 @@ struct virtio_net { struct vhost_virtqueue *virtqueue[VIRTIO_QNUM];/**< Contains all virtqueue information. */ struct virtio_memory*mem; /**< QEMU memory and memory region information. */ uint64_tfeatures; /**< Negotiated feature set. */ + uint64_tprotocol_features; /**< Negotiated protocol feature set. */ uint64_tdevice_fh; /**< device identifier. */ uint32_tflags; /**< Device flags. Only used to check if device is running on data core. */ #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ) diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c index d1f8877..bc2ad24 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.c +++ b/lib/librte_vhost/vhost_user/vhost-net-user.c @@ -95,7 +95,9 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_GET_VRING_BASE] = "VHOST_USER_GET_VRING_BASE", [VHOST_USER_SET_VRING_KICK] = "VHOST_USER_SET_VRING_KICK", [VHOST_USER_SET_VRING_CALL] = "VHOST_USER_SET_VRING_CALL", - [VHOST_USER_SET_VRING_ERR] = "VHOST_USER_SET_VRING_ERR" + [VHOST_USER_SET_VRING_ERR] = "VHOST_USER_SET_VRING_ERR", + [VHOST_USER_GET_PROTOCOL_FEATURES] = "VHOST_USER_GET_PROTOCOL_FEATURES", + [VHOST_USER_SET_PROTOCOL_FEATURES] = "VHOST_USER_SET_PROTOCOL_FEATURES", }; /** @@ -363,6 +365,15 @@ vserver_message_handler(int connfd, void *dat, int *remove) ops->set_features(ctx, &features); break; + case VHOST_USER_GET_PROTOCOL_FEATURES: + msg.payload.u64 = VHOST_USER_PROTOCOL_FEATURES; + msg.size = sizeof(msg.payload.u64); + send_vhost_message(connfd, &msg); + break; + case VHOST_USER_SET_PROTOCOL_FEATURES: + user_set_protocol_features(ctx, msg.payload.u64); + break; + case VHOST_USER_SET_OWNER: ops->set_owner(ctx); break; diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.h b/lib/librte_vhost/vhost_user/vhost-net-user.h index 2e72f3c..4490d23 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.h +++ b/lib/librte_vhost/vhost_user/vhost-net-user.h @@ -63,6 +63,8 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_KICK = 12, VHOST_USER_SET_VRING_CALL = 13, VHOST_USER_SET_VRING_ERR = 14, + VHOST_USER_GET_PROTOCOL_FEATURES = 15, + VHOST_USER_SET_PROTOCOL_FEATURES = 16, VHOST_USER_MAX } VhostUserRequest; diff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c index e0bc2a4..6da729d 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.c +++ b/lib/librte_vhost/vhost_user/virtio-net-user.c @@ -318,3 +318,16 @@ user_destroy_device(struct vhost_device_ctx ctx) dev->mem = NULL; } } + +void +user_set_protocol_features(struct vhost_device_ctx ctx, + uint64_t protocol_features) +{ + struct virtio_net *dev; + + dev = get_device(ctx); + if (dev == NULL || protocol_features & ~VHOST_USER_PROTOCOL_FEATURES) + return; + + dev->protocol_features = protocol_features; +} diff --git a/lib/librte_vhost/vhost_user/virtio-net-user.h b/lib/librte_vhost/vhost_user/virtio-net-user.h index df24860..e7a6ff4 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.h +++ b/lib/librte_vhost/vhost_user/virtio-net-user.h @@ -37,12 +37,17 @@ #include "vhost-net.h" #include "vhost-net-user.h" +#define VHOST_USER_PROTOCOL_FEATURES 0ULL + int user_set_mem_table(struct vhost_device_ctx, struct VhostUser
[dpdk-dev] [PATCH v8 2/8] vhost-user: add VHOST_USER_GET_QUEUE_NUM message
To tell the frontend (qemu) how many queue pairs we support. And it is initiated to VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX. Signed-off-by: Yuanhan Liu Acked-by: Flavio Leitner --- lib/librte_vhost/vhost_user/vhost-net-user.c | 7 +++ lib/librte_vhost/vhost_user/vhost-net-user.h | 1 + 2 files changed, 8 insertions(+) diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c index bc2ad24..8675cd4 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.c +++ b/lib/librte_vhost/vhost_user/vhost-net-user.c @@ -98,6 +98,7 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_SET_VRING_ERR] = "VHOST_USER_SET_VRING_ERR", [VHOST_USER_GET_PROTOCOL_FEATURES] = "VHOST_USER_GET_PROTOCOL_FEATURES", [VHOST_USER_SET_PROTOCOL_FEATURES] = "VHOST_USER_SET_PROTOCOL_FEATURES", + [VHOST_USER_GET_QUEUE_NUM] = "VHOST_USER_GET_QUEUE_NUM", }; /** @@ -421,6 +422,12 @@ vserver_message_handler(int connfd, void *dat, int *remove) RTE_LOG(INFO, VHOST_CONFIG, "not implemented\n"); break; + case VHOST_USER_GET_QUEUE_NUM: + msg.payload.u64 = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX; + msg.size = sizeof(msg.payload.u64); + send_vhost_message(connfd, &msg); + break; + default: break; diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.h b/lib/librte_vhost/vhost_user/vhost-net-user.h index 4490d23..389d21d 100644 --- a/lib/librte_vhost/vhost_user/vhost-net-user.h +++ b/lib/librte_vhost/vhost_user/vhost-net-user.h @@ -65,6 +65,7 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_ERR = 14, VHOST_USER_GET_PROTOCOL_FEATURES = 15, VHOST_USER_SET_PROTOCOL_FEATURES = 16, + VHOST_USER_GET_QUEUE_NUM = 17, VHOST_USER_MAX } VhostUserRequest; -- 1.9.0
[dpdk-dev] [PATCH v8 4/8] vhost: rxtx: use queue id instead of constant ring index
From: Changchun Ouyang Do not use VIRTIO_RXQ or VIRTIO_TXQ anymore; use the queue_id instead, which will be set to a proper value for a specific queue when we have multiple queue support enabled. For now, queue_id is still set with VIRTIO_RXQ or VIRTIO_TXQ, so it should not break anything. Signed-off-by: Changchun Ouyang Signed-off-by: Yuanhan Liu Acked-by: Flavio Leitner --- v8: simplify is_valid_vrit_queue_idx() v7: commit title fix --- lib/librte_vhost/vhost_rxtx.c | 43 +-- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/lib/librte_vhost/vhost_rxtx.c b/lib/librte_vhost/vhost_rxtx.c index 7026bfa..1ec8850 100644 --- a/lib/librte_vhost/vhost_rxtx.c +++ b/lib/librte_vhost/vhost_rxtx.c @@ -32,6 +32,7 @@ */ #include +#include #include #include @@ -42,6 +43,12 @@ #define MAX_PKT_BURST 32 +static bool +is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t qp_nb) +{ + return (is_tx ^ (idx & 1)) == 0 && idx < qp_nb * VIRTIO_QNUM; +} + /** * This function adds buffers to the virtio devices RX virtqueue. Buffers can * be received from the physical port or from another virtio device. A packet @@ -68,12 +75,14 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id, uint8_t success = 0; LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_rx()\n", dev->device_fh); - if (unlikely(queue_id != VIRTIO_RXQ)) { - LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); + if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) { + RTE_LOG(ERR, VHOST_DATA, + "%s (%"PRIu64"): virtqueue idx:%d invalid.\n", + __func__, dev->device_fh, queue_id); return 0; } - vq = dev->virtqueue[VIRTIO_RXQ]; + vq = dev->virtqueue[queue_id]; count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count; /* @@ -235,8 +244,9 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id, } static inline uint32_t __attribute__((always_inline)) -copy_from_mbuf_to_vring(struct virtio_net *dev, uint16_t res_base_idx, - uint16_t res_end_idx, struct rte_mbuf *pkt) +copy_from_mbuf_to_vring(struct virtio_net *dev, uint32_t queue_id, + uint16_t res_base_idx, uint16_t res_end_idx, + struct rte_mbuf *pkt) { uint32_t vec_idx = 0; uint32_t entry_success = 0; @@ -264,7 +274,7 @@ copy_from_mbuf_to_vring(struct virtio_net *dev, uint16_t res_base_idx, * Convert from gpa to vva * (guest physical addr -> vhost virtual addr) */ - vq = dev->virtqueue[VIRTIO_RXQ]; + vq = dev->virtqueue[queue_id]; vb_addr = gpa_to_vva(dev, vq->buf_vec[vec_idx].buf_addr); vb_hdr_addr = vb_addr; @@ -464,11 +474,14 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id, LOG_DEBUG(VHOST_DATA, "(%"PRIu64") virtio_dev_merge_rx()\n", dev->device_fh); - if (unlikely(queue_id != VIRTIO_RXQ)) { - LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); + if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) { + RTE_LOG(ERR, VHOST_DATA, + "%s (%"PRIu64"): virtqueue idx:%d invalid.\n", + __func__, dev->device_fh, queue_id); + return 0; } - vq = dev->virtqueue[VIRTIO_RXQ]; + vq = dev->virtqueue[queue_id]; count = RTE_MIN((uint32_t)MAX_PKT_BURST, count); if (count == 0) @@ -509,8 +522,8 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id, res_cur_idx); } while (success == 0); - entry_success = copy_from_mbuf_to_vring(dev, res_base_idx, - res_cur_idx, pkts[pkt_idx]); + entry_success = copy_from_mbuf_to_vring(dev, queue_id, + res_base_idx, res_cur_idx, pkts[pkt_idx]); rte_compiler_barrier(); @@ -562,12 +575,14 @@ rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id, uint16_t free_entries, entry_success = 0; uint16_t avail_idx; - if (unlikely(queue_id != VIRTIO_TXQ)) { - LOG_DEBUG(VHOST_DATA, "mq isn't supported in this version.\n"); + if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->virt_qp_nb))) { + RTE_LOG(ERR, VHOST_DATA, + "%s (%"PRIu64"): virtqueue idx:%d invalid.\n", + __func__, dev->device_fh, queue_id); return 0; } - vq = dev->virtqueue[VIRTIO_TXQ]; + vq = dev->virtqueue[queue_id]; avail_idx = *((volatile uint16_t *)&vq->avail->idx); /* If there are no available buffers then return. */ -- 1.9.0
[dpdk-dev] [PATCH v8 5/8] virtio: fix deadloop due to reading virtio_net_config incorrectly
From: Changchun Ouyang The old code adjusts the config bytes we want to read depending on what kind of features we have, but we later cast the entire buf we read with "struct virtio_net_config", which is obviously wrong. The wrong config reading results to a dead loop at virtio_send_command() while starting testpmd. The right way to go is to read related config bytes when corresponding feature is set, which is exactly what this patch does. Fixes: 823ad647950a ("virtio: support multiple queues") Signed-off-by: Changchun Ouyang Signed-off-by: Yuanhan Liu Acked-by: Flavio Leitner --- v7: commit log fixes v6: read mac unconditionally. --- drivers/net/virtio/virtio_ethdev.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 02f698a..12fcc23 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1162,7 +1162,6 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) struct virtio_hw *hw = eth_dev->data->dev_private; struct virtio_net_config *config; struct virtio_net_config local_config; - uint32_t offset_conf = sizeof(config->mac); struct rte_pci_device *pci_dev; RTE_BUILD_BUG_ON(RTE_PKTMBUF_HEADROOM < sizeof(struct virtio_net_hdr)); @@ -1225,8 +1224,14 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) if (vtpci_with_feature(hw, VIRTIO_NET_F_CTRL_VQ)) { config = &local_config; + vtpci_read_dev_config(hw, + offsetof(struct virtio_net_config, mac), + &config->mac, sizeof(config->mac)); + if (vtpci_with_feature(hw, VIRTIO_NET_F_STATUS)) { - offset_conf += sizeof(config->status); + vtpci_read_dev_config(hw, + offsetof(struct virtio_net_config, status), + &config->status, sizeof(config->status)); } else { PMD_INIT_LOG(DEBUG, "VIRTIO_NET_F_STATUS is not supported"); @@ -1234,15 +1239,16 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) } if (vtpci_with_feature(hw, VIRTIO_NET_F_MQ)) { - offset_conf += sizeof(config->max_virtqueue_pairs); + vtpci_read_dev_config(hw, + offsetof(struct virtio_net_config, max_virtqueue_pairs), + &config->max_virtqueue_pairs, + sizeof(config->max_virtqueue_pairs)); } else { PMD_INIT_LOG(DEBUG, "VIRTIO_NET_F_MQ is not supported"); config->max_virtqueue_pairs = 1; } - vtpci_read_dev_config(hw, 0, (uint8_t *)config, offset_conf); - hw->max_rx_queues = (VIRTIO_MAX_RX_QUEUES < config->max_virtqueue_pairs) ? VIRTIO_MAX_RX_QUEUES : config->max_virtqueue_pairs; -- 1.9.0
[dpdk-dev] [PATCH v8 3/8] vhost: vring queue setup for multiple queue support
All queue pairs, including the default (the first) queue pair, are allocated dynamically, when a vring_call message is received first time for a specific queue pair. This is a refactor work for enabling vhost-user multiple queue; it should not break anything as it does no functional changes: we don't support mq set, so there is only one mq at max. This patch is based on Changchun's patch. Signed-off-by: Ouyang Changchun Signed-off-by: Yuanhan Liu Acked-by: Flavio Leitner --- v8: - move virtuque field to the end of `virtio_net' struct. - Add a FIXME at set_vring_call() for doing vring queue pair allocation. --- lib/librte_vhost/rte_virtio_net.h | 3 +- lib/librte_vhost/vhost_user/virtio-net-user.c | 46 lib/librte_vhost/virtio-net.c | 156 -- 3 files changed, 123 insertions(+), 82 deletions(-) diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h index e3a21e5..9a32a95 100644 --- a/lib/librte_vhost/rte_virtio_net.h +++ b/lib/librte_vhost/rte_virtio_net.h @@ -96,7 +96,6 @@ struct vhost_virtqueue { * Device structure contains all configuration information relating to the device. */ struct virtio_net { - struct vhost_virtqueue *virtqueue[VIRTIO_QNUM];/**< Contains all virtqueue information. */ struct virtio_memory*mem; /**< QEMU memory and memory region information. */ uint64_tfeatures; /**< Negotiated feature set. */ uint64_tprotocol_features; /**< Negotiated protocol feature set. */ @@ -104,7 +103,9 @@ struct virtio_net { uint32_tflags; /**< Device flags. Only used to check if device is running on data core. */ #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ) charifname[IF_NAME_SZ]; /**< Name of the tap device or socket path. */ + uint32_tvirt_qp_nb; /**< number of queue pair we have allocated */ void*priv; /**< private context */ + struct vhost_virtqueue *virtqueue[VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX]; /**< Contains all virtqueue information. */ } __rte_cache_aligned; /** diff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c index 6da729d..d62f3d7 100644 --- a/lib/librte_vhost/vhost_user/virtio-net-user.c +++ b/lib/librte_vhost/vhost_user/virtio-net-user.c @@ -206,25 +206,33 @@ err_mmap: } static int +vq_is_ready(struct vhost_virtqueue *vq) +{ + return vq && vq->desc && + vq->kickfd != -1 && + vq->callfd != -1; +} + +static int virtio_is_ready(struct virtio_net *dev) { struct vhost_virtqueue *rvq, *tvq; + uint32_t i; - /* mq support in future.*/ - rvq = dev->virtqueue[VIRTIO_RXQ]; - tvq = dev->virtqueue[VIRTIO_TXQ]; - if (rvq && tvq && rvq->desc && tvq->desc && - (rvq->kickfd != -1) && - (rvq->callfd != -1) && - (tvq->kickfd != -1) && - (tvq->callfd != -1)) { - RTE_LOG(INFO, VHOST_CONFIG, - "virtio is now ready for processing.\n"); - return 1; + for (i = 0; i < dev->virt_qp_nb; i++) { + rvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ]; + tvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ]; + + if (!vq_is_ready(rvq) || !vq_is_ready(tvq)) { + RTE_LOG(INFO, VHOST_CONFIG, + "virtio is not ready for processing.\n"); + return 0; + } } + RTE_LOG(INFO, VHOST_CONFIG, - "virtio isn't ready for processing.\n"); - return 0; + "virtio is now ready for processing.\n"); + return 1; } void @@ -292,13 +300,13 @@ user_get_vring_base(struct vhost_device_ctx ctx, * sent and only sent in vhost_vring_stop. * TODO: cleanup the vring, it isn't usable since here. */ - if ((dev->virtqueue[VIRTIO_RXQ]->kickfd) >= 0) { - close(dev->virtqueue[VIRTIO_RXQ]->kickfd); - dev->virtqueue[VIRTIO_RXQ]->kickfd = -1; + if ((dev->virtqueue[state->index]->kickfd + VIRTIO_RXQ) >= 0) { + close(dev->virtqueue[state->index + VIRTIO_RXQ]->kickfd); + dev->virtqueue[state->index + VIRTIO_RXQ]->kickfd = -1; } - if ((dev->virtqueue[VIRTIO_TXQ]->kickfd) >= 0) { - close(dev->virtqueue[VIRTIO_TXQ]->kickfd); - dev->virtqueue[VIRTIO_TXQ]->kickfd = -1; + if ((dev->virtqueue[state->index]->kickfd + VIRTIO_TXQ) >= 0) { + close(dev->virtqueue[state->index + VIRTIO_TXQ]->kickfd); + dev->virtqueue[state->index + VIRTIO_TXQ]->kickfd = -1; } return 0; diff --git a/lib/librte_vhost/virtio-net