ethdev: introduce shared Rx queue
Subsystems (2)
PATCH v2 14/15 app/testpmd: support shared Rx queue for 5tuple fwd
In reply to Xueming LiFrom: Xiaoyu Min <[email protected]>
Add support of shared rxq.
If shared rxq is enabled, filter packet by stream according to mbuf->port value and then fwd it in stream basis (as before).
If shared rxq is not enabled, just fwd it as usual in stream basis.
--- app/test-pmd/5tswap.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-)
app/test-pmd/5tswap.c +11 -19
@@ -82,18 +82,16 @@ swap_udp(struct rte_udp_hdr *udp_hdr)* Parses each layer and swaps it. When the next layer doesn't match it stops. */ static void -pkt_burst_5tuple_swap (struct fwd_stream *fs) +_5tuple_swap_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_port *txp;struct rte_mbuf *mb;uint16_t next_proto;uint64_t ol_flags;uint16_t proto; -uint16_t nb_rx;uint16_t nb_tx;uint32_t retry; -int i;union {struct rte_ether_hdr *eth;
@@ -105,20 +103,6 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)uint8_t *byte; } h; -uint64_t start_tsc =0 ; - -get_start_cycles (&start_tsc); - -/* -* Receive a burst of packets and forward them. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; txp = &ports[fs->tx_port]; ol_flags =ol_flags_init (txp->dev_conf.txmode.offloads); vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
@@ -182,7 +166,15 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)rte_pktmbuf_free (pkts_burst[nb_tx]); }while (++nb_tx < nb_rx); } -get_end_cycles (fs, start_tsc); +} + +/* +* Wrapper of real fwd engine. +*/ +static void +pkt_burst_5tuple_swap (struct fwd_stream *fs) +{ +return do_burst_fwd (fs, _5tuple_swap_stream); }struct fwd_engine five_tuple_swap_fwd_engine = {
Signature · 1 line
2.25.1
PATCH v2 15/15 app/testpmd: support shared Rx queue for ieee1588 fwd
In reply to Xueming LiFrom: Xiaoyu Min <[email protected]>
Add support of shared rxq.
If shared rxq is enabled, filter packet by stream according to mbuf->port value and then fwd it in stream basis (as before).
If shared rxq is not enabled, just fwd it as usual in stream basis.
--- app/test-pmd/ieee1588fwd.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
app/test-pmd/ieee1588fwd.c +20 -10
@@ -90,23 +90,17 @@ port_ieee1588_tx_timestamp_check(portid_t pi) }static void -ieee1588_packet_fwd (struct fwd_stream *fs) +ieee1588_fwd_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkt) { -struct rte_mbuf *mb; +struct rte_mbuf *mb = (*pkt);struct rte_ether_hdr *eth_hdr;struct rte_ether_addr addr;struct ptpv2_msg *ptp_hdr;uint16_t eth_type;uint32_t timesync_index; -/* -* Receive 1 packet at a time. -*/ -if (rte_eth_rx_burst (fs->rx_port, fs->rx_queue, &mb,1 ) ==0 ) -return ; - - fs->rx_packets +=1 ; - +RTE_SET_USED (nb_rx);/* * Check that the received packet is a PTP packet that was detected * by the hardware.
@@ -198,6 +192,22 @@ ieee1588_packet_fwd(struct fwd_stream *fs)port_ieee1588_tx_timestamp_check (fs->rx_port); } +/* +* Wrapper of real fwd ingine. +*/ +static void +ieee1588_packet_fwd (struct fwd_stream *fs) +{ +struct rte_mbuf *mb; + +if (rte_eth_rx_burst (fs->rx_port, fs->rx_queue, &mb,1 ) ==0 ) +return ; +if (unlikely (rxq_share >0 )) +forward_shared_rxq (fs,1 , &mb, ieee1588_fwd_stream); +else +ieee1588_fwd_stream (fs,1 , &mb); +} +static void port_ieee1588_fwd_begin (portid_t pi) {
Signature · 1 line
2.25.1
Quoted 32 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html#undef
RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +0
-0
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1050
Quoted 4 lines
lib/ethdev/rte_ethdev.h +1
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */
Not to able to see anyone setting/creating this group ID test application. How this group is created?
Quoted 19 lines
lib/ethdev/rte_ethdev.h +6
-1/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1373,6 +1374,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 38 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 26 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html
Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h index renamed from lib/ethdev/rte_ethdev.h +0
-0
d2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch +domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group number, but user must schedule stream affinity carefully - error prone.
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Quoted 22 lines
Quoted 22 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-1+/** +* Rx queue is shared among ports in same switch domain to save +memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 61 lines · Xueming(Steven) Li
Quoted 39 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 26 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.htmlQuoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h index renamed from lib/ethdev/rte_ethdev.h +0
-0
d2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch +domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
Quoted 7 lines
To support more groups simultaneously, need to consider testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group number, but user must schedule stream affinity carefully - error prone.
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created, Should n't we need API to create shared_group? If we do the following, at least, I can think, how it
can be implemented in SW or other HW.
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queue group(which internally fetch from the Rx queues _attached_)
Does the above kind of sequence, break your representor use case?
Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-1+/** +* Rx queue is shared among ports in same switch domain to save +memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 83 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 62 lines · Xueming(Steven) Li
Quoted 40 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 26 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from
all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.htmlQuoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in +switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
Quoted 7 lines
To support more groups simultaneously, need to consider testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group number, but user must schedule stream affinity carefully - error prone.
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
Quoted 8 lines
My question was more about who and how this group is created, Should n't we need API to create
shared_group? If we do the following, at least, I can think, how it can be implemented in SW or other HW.- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, in rte_flow, group is created on demand.
- step 2, currently, the attaching is done in rte_eth_rx_queue_setup, specify offload and group in rx_conf struct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callback eth_rx_burst_t(rxq_obj, mbufs, n) could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
Quoted 25 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-1+/** +* Rx queue is shared among ports in same switch domain to save +memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 87 lines · Xueming(Steven) Li
Quoted 87 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 62 lines · Xueming(Steven) Li
Quoted 40 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 26 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from
all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.htmlQuoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in +switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
Quoted 7 lines
To support more groups simultaneously, need to consider testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group number, but user must schedule stream affinity carefully - error prone.
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created, Should n't we need API to create
shared_group? If we do the following, at least, I can think, how it can be implemented in SW or other HW.
Quoted 8 lines
Quoted 5 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.
Which rte_flow pattern/action for this?
Quoted 8 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure SW thing, If it is SW, It is better to have
just new vdev for like drivers/net/bonding/. This we can help aggregate multiple Rxq across the multiple ports
of same the driver.
Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
Quoted 26 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-1+/** +* Rx queue is shared among ports in same switch domain to save +memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 105 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 94 lines · Xueming(Steven) Li
Quoted 94 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 63 lines · Xueming(Steven) Li
Quoted 41 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 26 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets
from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.htmlQuoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in +switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
Quoted 7 lines
To support more groups simultaneously, need to consider testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group number,
but user must schedule stream affinity carefully - error prone.On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created, Should
n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SW or other HW.- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
Does the above kind of sequence, break your representor use case?
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?
No rte_flow for this, just recalled that the group in rte_flow is not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.
Quoted 8 lines
Quoted 8 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure SW thing, If it is SW, It is better to have just new vdev for like
drivers/net/bonding/. This we can help aggregate multiple Rxq across the multiple ports of same the driver.
Based on HW support.
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough. Anyway, welcome any suggestion.
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-1+/** +* Rx queue is shared among ports in same switch domain to +save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 108 lines · Xueming(Steven) Li
Quoted 108 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 96 lines · Xueming(Steven) Li
Quoted 95 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 63 lines · Xueming(Steven) Li
Quoted 41 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 26 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets
from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.htmlQuoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in +switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
Quoted 7 lines
To support more groups simultaneously, need to consider testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group number,
but user must schedule stream affinity carefully - error prone.On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created, Should
n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SW or other HW.- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.
See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure SW thing, If it is SW, It is better to have just new vdev for like
drivers/net/bonding/. This we can help aggregate multiple Rxq across the multiple ports of same the driver.Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect each Rxq to the new HW structure for aggregation # Use rx_burst from the new HW structure.
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory, atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.
How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more eth_dev_ops in driver as aggregator ethdev
# devargs of new ethdev or specific API like drivers/net/bonding/rte_eth_bond.h can take the argument (port, queue) tuples which needs to aggregate by new ethdev port # No change in fastpath or ABI is required in this model.
Quoted 32 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough. Anyway, welcome any suggestion.
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
Quoted 28 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-1+/** +* Rx queue is shared among ports in same switch domain to +save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.25.1
Quoted 156 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 26, 2021 7:58 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 97 lines · Xueming(Steven) Li
Quoted 97 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 84 lines · Xueming(Steven) Li
Quoted 84 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 70 lines · Xueming(Steven) Li
Quoted 43 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 27 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives
packets from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object,
it's important to clear all queue control callback api that using queue object:Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group +index in switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider
testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group
number, but user must schedule stream affinity carefully - error prone.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created,
Should n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SWor other HW.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure
SW thing, If it is SW, It is better to have just new vdev for likedrivers/net/bonding/. This we can help aggregate multiple Rxq acrossthe multiple ports of same the driver.
Quoted 2 lines
Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect each Rxq to the new HW structure for aggregation # Use
rx_burstfrom the new HW structure.
Quoted 7 lines
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory, atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.
How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
Glad to know that Marvel is working on this, what's the status of driver implementation?
In my PMD implementation, it's very similar, a new HW object shared memory pool is created to replace per rxq memory pool. Legacy rxq feed queue with allocated mbufs as number of descriptors, now shared rxqs share the same pool, no need to supply mbufs for each rxq, just feed the shared rxq.
So the memory saving reflects to mbuf per rxq, even 1000 representors in shared rxq group, the mbufs consumed is one rxq. In other words, new members in shared rxq doesn’t allocate new mbufs to feed rxq, just share with existing shared rxq(HW mempool). The memory required to setup each rxq doesn't change too much, agree.
Quoted 6 lines
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more
eth_dev_opsin driver as aggregator ethdev # devargs of new ethdev or specific API likedrivers/net/bonding/rte_eth_bond.hcan take the argument (port, queue) tuples which needs to aggregate by new ethdev port # No change in fastpath or ABI is required in this model.
This could be an option to access shared rxq. What's the difference of the new PMD? What's the difference of PMD driver to create the new device?
Is it important in your implementation? Does it work with existing rx_burst api?
Quoted 36 lines
Quoted 5 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot
plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough.Anyway, welcome any suggestion.
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-0+/** +* Rx queue is shared among ports in same switch domain +to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM| \
--
2.25.1
Quoted 167 lines · Xueming(Steven) Li
Quoted 157 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 26, 2021 7:58 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 97 lines · Xueming(Steven) Li
Quoted 97 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 84 lines · Xueming(Steven) Li
Quoted 84 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 70 lines · Xueming(Steven) Li
Quoted 43 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 27 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives
packets from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object,
it's important to clear all queue control callback api that using queue object:Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group +index in switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider
testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group
number, but user must schedule stream affinity carefully - error prone.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created,
Should n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SWor other HW.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure
SW thing, If it is SW, It is better to have just new vdev for likedrivers/net/bonding/. This we can help aggregate multiple Rxq acrossthe multiple ports of same the driver.
Quoted 2 lines
Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect each Rxq to the new HW structure for aggregation # Use
rx_burstfrom the new HW structure.Quoted 7 lines
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory, atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.
How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
Glad to know that Marvel is working on this, what's the status of driver implementation?
Quoted 7 lines
In my PMD implementation, it's very similar, a new HW object shared memory pool is created to replace per rxq memory pool. Legacy rxq feed queue with allocated mbufs as number of descriptors, now shared rxqs share the same pool, no need to supply mbufs for each rxq, just feed the shared rxq.
So the memory saving reflects to mbuf per rxq, even 1000 representors in shared rxq group, the mbufs consumed is one rxq. In other words, new members in shared rxq doesn’t allocate new mbufs to feed rxq, just share with existing shared rxq(HW mempool). The memory required to setup each rxq doesn't change too much, agree.
We can ask the application to configure the same mempool for multiple RQ too. RIght? If the saving is based on sharing the mempool with multiple RQs.
Quoted 9 lines
Quoted 7 lines
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more
eth_dev_opsin driver as aggregator ethdev # devargs of new ethdev or specific API likedrivers/net/bonding/rte_eth_bond.hcan take the argument (port, queue) tuples which needs to aggregate by new ethdev port # No change in fastpath or ABI is required in this model.This could be an option to access shared rxq. What's the difference of the new PMD?
No ABI and fast change are required.
Quoted 3 lines
What's the difference of PMD driver to create the new device?
Is it important in your implementation? Does it work with existing
rx_burstapi?
Yes . It will work with the existing rx_burst API.
Quoted 37 lines
Quoted 37 lines
Quoted 6 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot
plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough.Anyway, welcome any suggestion.
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-0+/** +* Rx queue is shared among ports in same switch domain +to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM| \
--
2.25.1
Quoted 190 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Monday, August 30, 2021 5:31 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 179 lines · Xueming(Steven) Li
Quoted 165 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 26, 2021 7:58 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 103 lines · Xueming(Steven) Li
Quoted 103 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 89 lines · Xueming(Steven) Li
Quoted 89 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 73 lines · Xueming(Steven) Li
Quoted 44 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 28 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded
with mbufs for incoming packets. When number of
representors scale out in a switch domain, the memory consumption became significant. Most important,
polling all ports leads to high cache miss, high latency and low throughput.This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives
packets from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue
object, it's important to clear all queue control callback api that using queue object:Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group +index in switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider
testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group
number, but user must schedule stream affinity carefully - error prone.On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Ack. One group is enough in testpmd.
My question was more about who and how this group is created, Should n't we need API to create
shared_group? If we do the following, at least, I can think, how it can be implemented in SWor other HW.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Quoted 6 lines
Quoted 6 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure SW thing, If it is SW, It is better to have just new vdev for like
drivers/net/bonding/. This we can help aggregate multiple Rxq acrossthe multiple ports of same the driver.
Quoted 2 lines
Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect
each Rxq to the new HW structure for aggregation # Userx_burstfrom the new HW structure.Quoted 7 lines
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory,
atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
Glad to know that Marvel is working on this, what's the status of driver implementation?
In my PMD implementation, it's very similar, a new HW object shared memory pool is created to replace per rxq memory pool. Legacy rxq feed queue with allocated mbufs as number of descriptors,
now shared rxqs share the same pool, no need to supply mbufs for each rxq, just feed the shared rxq.
Quoted 7 lines
Quoted 2 lines
So the memory saving reflects to mbuf per rxq, even 1000 representors in shared rxq group, the mbufs consumed is one rxq. In other words, new members in shared rxq doesn’t allocate new mbufs to feed rxq, just share with existing shared rxq(HW
mempool).
Quoted 1 line
The memory required to setup each rxq doesn't change too much, agree.
We can ask the application to configure the same mempool for multiple RQ too. RIght? If the saving is based on sharing the mempool with multiple RQs.
Yes, using the same mempool is the fundamental. The difference is how many mbufs allocate from pool. Assuming 512 descriptors perf rxq and 4 rxqs per device, it's 2.3K(mbuf) * 512 * 4 = 4.6M / device To support 1000 representors, need a 4.6G mempool :)
For shared rxq, only 4.6M(one device) mbufs allocate from mempool, they are shared for all rxqs in group.
Quoted 58 lines
Quoted 7 lines
Quoted 7 lines
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more
eth_dev_opsin driver as aggregator
ethdev # devargs of new ethdev or specific API likedrivers/net/bonding/rte_eth_bond.hcan take the argument (port, queue) tuples which needs to aggregate by new ethdev port #No change in fastpath or ABI is required in this model.
Quoted 3 lines
Quoted 1 line
This could be an option to access shared rxq. What's the difference of the new PMD?
No ABI and fast change are required.
Quoted 3 lines
What's the difference of PMD driver to create the new device?
Is it important in your implementation? Does it work with existing
rx_burstapi?Yes . It will work with the existing
rx_burstAPI.Quoted 38 lines
Quoted 38 lines
Quoted 6 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot
plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough.Anyway, welcome any suggestion.
Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
Quoted 31 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-0+/** +* Rx queue is shared among ports in same switch +domain to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \
DEV_RX_OFFLOAD_UDP_CKSUM
| \
--
2.25.1
Hi Jerin,
Quoted 190 lines · Jerin Jacob
Quoted 167 lines · Xueming(Steven) Li
Quoted 157 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 26, 2021 7:58 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 97 lines · Xueming(Steven) Li
Quoted 97 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 84 lines · Xueming(Steven) Li
Quoted 84 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 70 lines · Xueming(Steven) Li
Quoted 43 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 27 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives
packets from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object,
it's important to clear all queue control callback api that using queue object:Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group +index in switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider
testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group
number, but user must schedule stream affinity carefully - error prone.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created,
Should n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SWor other HW.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure
SW thing, If it is SW, It is better to have just new vdev for likedrivers/net/bonding/. This we can help aggregate multiple Rxq acrossthe multiple ports of same the driver.
Quoted 2 lines
Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect each Rxq to the new HW structure for aggregation # Use
rx_burstfrom the new HW structure.Quoted 7 lines
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory, atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.
How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
Glad to know that Marvel is working on this, what's the status of driver implementation?
Quoted 7 lines
In my PMD implementation, it's very similar, a new HW object shared memory pool is created to replace per rxq memory pool. Legacy rxq feed queue with allocated mbufs as number of descriptors, now shared rxqs share the same pool, no need to supply mbufs for each rxq, just feed the shared rxq.
So the memory saving reflects to mbuf per rxq, even 1000 representors in shared rxq group, the mbufs consumed is one rxq. In other words, new members in shared rxq doesn’t allocate new mbufs to feed rxq, just share with existing shared rxq(HW mempool). The memory required to setup each rxq doesn't change too much, agree.
We can ask the application to configure the same mempool for multiple RQ too. RIght? If the saving is based on sharing the mempool with multiple RQs.
Quoted 9 lines
Quoted 7 lines
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more
eth_dev_opsin driver as aggregator ethdev # devargs of new ethdev or specific API likedrivers/net/bonding/rte_eth_bond.hcan take the argument (port, queue) tuples which needs to aggregate by new ethdev port # No change in fastpath or ABI is required in this model.This could be an option to access shared rxq. What's the difference of the new PMD?
Quoted 8 lines
No ABI and fast change are required.
Quoted 3 lines
What's the difference of PMD driver to create the new device?
Is it important in your implementation? Does it work with existing
rx_burstapi?Yes . It will work with the existing
rx_burstAPI.
The aggregator ethdev required by user is a port, maybe it good to add a callback for PMD to prepare a complete ethdev just like creating representor ethdev - pmd register new port internally. If the PMD doens't provide the callback, ethdev api fallback to initialize an empty ethdev by copy rxq data(shared) and rx_burst api from source port and share group. Actually users can do this fallback themselves or with an util api.
IIUC, an aggregator ethdev not a must, do you think we can continue and leave that design in later stage?
Quoted 37 lines
Quoted 37 lines
Quoted 37 lines
Quoted 6 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot
plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough.Anyway, welcome any suggestion.
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-0+/** +* Rx queue is shared among ports in same switch domain +to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUMQuoted 1 line
\
--
2.25.1
Quoted 211 lines · Xueming(Steven) Li
Hi Jerin,
Quoted 190 lines · Jerin Jacob
Quoted 167 lines · Xueming(Steven) Li
Quoted 157 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 26, 2021 7:58 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 97 lines · Xueming(Steven) Li
Quoted 97 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 84 lines · Xueming(Steven) Li
Quoted 84 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 70 lines · Xueming(Steven) Li
Quoted 43 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 27 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives
packets from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object,
it's important to clear all queue control callback api that using queue object:Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group +index in switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider
testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group
number, but user must schedule stream affinity carefully - error prone.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created,
Should n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SWor other HW.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure
SW thing, If it is SW, It is better to have just new vdev for likedrivers/net/bonding/. This we can help aggregate multiple Rxq acrossthe multiple ports of same the driver.
Quoted 2 lines
Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect each Rxq to the new HW structure for aggregation # Use
rx_burstfrom the new HW structure.Quoted 7 lines
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory, atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.
How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
Glad to know that Marvel is working on this, what's the status of driver implementation?
Quoted 7 lines
In my PMD implementation, it's very similar, a new HW object shared memory pool is created to replace per rxq memory pool. Legacy rxq feed queue with allocated mbufs as number of descriptors, now shared rxqs share the same pool, no need to supply mbufs for each rxq, just feed the shared rxq.
So the memory saving reflects to mbuf per rxq, even 1000 representors in shared rxq group, the mbufs consumed is one rxq. In other words, new members in shared rxq doesn’t allocate new mbufs to feed rxq, just share with existing shared rxq(HW mempool). The memory required to setup each rxq doesn't change too much, agree.
We can ask the application to configure the same mempool for multiple RQ too. RIght? If the saving is based on sharing the mempool with multiple RQs.
Quoted 9 lines
Quoted 7 lines
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more
eth_dev_opsin driver as aggregator ethdev # devargs of new ethdev or specific API likedrivers/net/bonding/rte_eth_bond.hcan take the argument (port, queue) tuples which needs to aggregate by new ethdev port # No change in fastpath or ABI is required in this model.This could be an option to access shared rxq. What's the difference of the new PMD?
Quoted 8 lines
No ABI and fast change are required.
Quoted 3 lines
What's the difference of PMD driver to create the new device?
Is it important in your implementation? Does it work with existing
rx_burstapi?Yes . It will work with the existing
rx_burstAPI.The aggregator ethdev required by user is a port, maybe it good to add a callback for PMD to prepare a complete ethdev just like creating representor ethdev - pmd register new port internally. If the PMD doens't provide the callback, ethdev api fallback to initialize an empty ethdev by copy rxq data(shared) and
rx_burstapi from source port and share group. Actually users can do this fallback themselves or with an util api.
Quoted 2 lines
IIUC, an aggregator ethdev not a must, do you think we can continue and leave that design in later stage?
IMO aggregator ethdev reduces the complexity for application hence avoid any change in
test application etc. IMO, I prefer to take that. I will leave the decision to ethdev maintainers.
Quoted 39 lines
Quoted 38 lines
Quoted 38 lines
Quoted 38 lines
Quoted 7 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot
plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough.Anyway, welcome any suggestion.
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-0+/** +* Rx queue is shared among ports in same switch domain +to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUMQuoted 1 line
\
--
2.25.1
Quoted 212 lines · Jerin Jacob
Quoted 211 lines · Xueming(Steven) Li
Hi Jerin,
Quoted 190 lines · Jerin Jacob
Quoted 167 lines · Xueming(Steven) Li
Quoted 157 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 26, 2021 7:58 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 97 lines · Xueming(Steven) Li
Quoted 97 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Thursday, August 19, 2021 1:27 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 84 lines · Xueming(Steven) Li
Quoted 84 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 11:12 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 70 lines · Xueming(Steven) Li
Quoted 43 lines
-----Original Message-----
From: Jerin Jacob <[email protected]>
Sent: Tuesday, August 17, 2021 5:33 PM
To: Xueming(Steven) Li <[email protected]>
Cc: dpdk-dev <[email protected]>; Ferruh Yigit <[email protected]>; NBU-Contact-Thomas Monjalon <[email protected]>; Andrew Rybchenko <[email protected]>
Subject: Re: [PATCH v2 01/15] ethdev: introduce shared Rx queueQuoted 27 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same
configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives
packets from all member ports. Source port is identified bymbuf->port.Port queue number in a shared group should be identical. Queue index is
1:1 mapped in shared group.Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object,
it's important to clear all queue control callback api that using queue object:Quoted 15 lines
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1052
Quoted 12 lines
#undef
RTE_RX_OFFLOAD_BIT2STRdiff --gita/lib/ethdev/rte_ethdev.hb/lib/ethdev/rte_ethdev.hindexd2b27c351f..a578c9db9d100644lib/ethdev/rte_ethdev.h +2
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group +index in switch domain. */ Not to able to see anyone setting/creating this group ID test application. How this group is created?
Nice catch, the initial testpmd version only support one default group(0). All ports that supports shared-rxq assigned in same group.
We should be able to change "--rxq-shared" to "--rxq-shared-group" to support group other than default.
To support more groups simultaneously, need to consider
testpmd forwarding stream core assignment, all streams in same group need to stay on same core. It's possible to specify how many ports to increase group
number, but user must schedule stream affinity carefully - error prone.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
On the other hand, one group should be sufficient for most customer, the doubt is whether it valuable to support multiple groups test.
Ack. One group is enough in testpmd.
My question was more about who and how this group is created,
Should n't we need API to createshared_group? If we do the following, at least, I can think, how it can be implemented in SWor other HW.
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
- Create aggregation queue group
- Attach multiple Rx queues to the aggregation queue group
- Pull the packets from the queuegroup(which internally fetch from the Rx queues _attached_)Does the above kind of sequence, break your representor use case?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
Seems more like a set of EAL wrapper. Current API tries to minimize the application efforts to adapt shared-rxq.
- step 1, not sure how important it is to create group with API, inrte_flow, group is created on demand.Which
rte_flowpattern/action for this?No
rte_flowfor this, just recalled that the group inrte_flowis not created along with flow, not via api. I don’t see anything else to create along with group, just double whether it valuable to introduce a new api set to manage group.See below.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
- step 2, currently, the attaching is done in
rte_eth_rx_queue_setup, specify offload and group inrx_confstruct.
- step 3, define a dedicate api to receive packets from shared rxq? Looks clear to receive packets from shared rxq. currently, rxq objects in share group is same - the shared rxq, so the eth callbacketh_rx_burst_t(rxq_obj, mbufs, n)could be used to receive packets from any ports in group, normally the first port(PF) in group.
An alternative way is defining a vdev with same queue number and copy rxq objects will make the vdev a proxy of the shared rxq group - this could be an helper API.Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Anyway the wrapper doesn't break use case, step 3 api is more clear, need to understand how to implement efficiently.
Are you doing this feature based on any HW support or it just pure
SW thing, If it is SW, It is better to have just new vdev for likedrivers/net/bonding/. This we can help aggregate multiple Rxq acrossthe multiple ports of same the driver.
Quoted 2 lines
Based on HW support.
In Marvel HW, we do some support, I will outline here and some queries on this.
# We need to create some new HW structure for aggregation # Connect each Rxq to the new HW structure for aggregation # Use
rx_burstfrom the new HW structure.Quoted 7 lines
Could you outline your HW support?
Also, I am not able to understand how this will reduce the memory, atleast in our HW need creating more memory now to deal this as we need to deal new HW structure.
How is in your HW it reduces the memory? Also, if memory is the constraint, why NOT reduce the number of queues.
Glad to know that Marvel is working on this, what's the status of driver implementation?
Quoted 7 lines
In my PMD implementation, it's very similar, a new HW object shared memory pool is created to replace per rxq memory pool. Legacy rxq feed queue with allocated mbufs as number of descriptors, now shared rxqs share the same pool, no need to supply mbufs for each rxq, just feed the shared rxq.
So the memory saving reflects to mbuf per rxq, even 1000 representors in shared rxq group, the mbufs consumed is one rxq. In other words, new members in shared rxq doesn’t allocate new mbufs to feed rxq, just share with existing shared rxq(HW mempool). The memory required to setup each rxq doesn't change too much, agree.
We can ask the application to configure the same mempool for multiple RQ too. RIght? If the saving is based on sharing the mempool with multiple RQs.
Quoted 9 lines
Quoted 7 lines
# Also, I was thinking, one way to avoid the fast path or ABI change would like.
# Driver Initializes one more
eth_dev_opsin driver as aggregator ethdev # devargs of new ethdev or specific API likedrivers/net/bonding/rte_eth_bond.hcan take the argument (port, queue) tuples which needs to aggregate by new ethdev port # No change in fastpath or ABI is required in this model.This could be an option to access shared rxq. What's the difference of the new PMD?
Quoted 8 lines
No ABI and fast change are required.
Quoted 3 lines
What's the difference of PMD driver to create the new device?
Is it important in your implementation? Does it work with existing
rx_burstapi?Yes . It will work with the existing
rx_burstAPI.The aggregator ethdev required by user is a port, maybe it good to add a callback for PMD to prepare a complete ethdev just like creating representor ethdev - pmd register new port internally. If the PMD doens't provide the callback, ethdev api fallback to initialize an empty ethdev by copy rxq data(shared) and
rx_burstapi from source port and share group. Actually users can do this fallback themselves or with an util api.
Quoted 8 lines
Quoted 2 lines
IIUC, an aggregator ethdev not a must, do you think we can continue and leave that design in later stage?
IMO aggregator ethdev reduces the complexity for application hence avoid any change in
test application etc. IMO, I prefer to take that. I will leave the decision to ethdev maintainers.
Hi Jerin, new API added for aggregator, the last one in v3, thanks!
Quoted 41 lines
Quoted 41 lines
Quoted 40 lines
Quoted 40 lines
Quoted 40 lines
Quoted 9 lines
Most user might uses PF in group as the anchor port to rx burst, current definition should be easy for them to migrate. but some user might prefer grouping some hot
plug/unpluggedrepresentors, EAL could provide wrappers, users could do that either due to the strategy not complex enough.Anyway, welcome any suggestion.
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
Quoted 30 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or
rx_offload_capa@@ -1373,6 +1374,12 @@ structrte_eth_conf{ #defineDEV_RX_OFFLOAD_OUTER_UDP_CKSUM0x00040000
#defineDEV_RX_OFFLOAD_RSS_HASH0x00080000
#defineRTE_ETH_RX_OFFLOAD_BUFFER_SPLIT0x00100000lib/ethdev/rte_ethdev.h +7
-0+/** +* Rx queue is shared among ports in same switch domain +to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUMQuoted 1 line
\
--
2.25.1
v3 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggerate shared rxq group
Xiaoyu Min (1):
app/testpmd: add common fwd wrapper
Xueming Li (7):
ethdev: introduce shared Rx queue
ethdev: new API to aggregate shared Rx queue group app/testpmd: dump port and queue info for each packet app/testpmd: new parameter to enable shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: improve forwarding cache miss app/testpmd: support shared Rx queue forwarding
app/test-pmd/5tswap.c | 25 +--- app/test-pmd/config.c | 120 +++++++++++++++++- app/test-pmd/csumonly.c | 25 +--- app/test-pmd/flowgen.c | 26 ++-- app/test-pmd/icmpecho.c | 30 ++--- app/test-pmd/ieee1588fwd.c | 30 +++-- app/test-pmd/iofwd.c | 24 +--- app/test-pmd/macfwd.c | 24 +--- app/test-pmd/macswap.c | 23 +--- app/test-pmd/noisy_vnf.c | 2 +- app/test-pmd/parameters.c | 13 ++ app/test-pmd/rxonly.c | 32 ++--- app/test-pmd/testpmd.c | 91 ++++++++++++- app/test-pmd/testpmd.h | 47 ++++++- app/test-pmd/txonly.c | 8 +- app/test-pmd/util.c | 1 + doc/guides/nics/features.rst | 11 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 ++ doc/guides/testpmd_app_ug/run_app.rst | 5 + lib/ethdev/ethdev_driver.h | 23 +++- lib/ethdev/rte_ethdev.c | 23 ++++ lib/ethdev/rte_ethdev.h | 23 ++++ lib/ethdev/version.map | 3 + 24 files changed, 432 insertions(+), 188 deletions(-)
Signature · 1 line
2.33.0
PATCH v3 1/8 ethdev: introduce shared Rx queue
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by mbuf->port.
Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html
--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 5 files changed, 30 insertions(+)
doc/guides/nics/features.rst +11 -0
@@ -624,6 +624,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +10 -0
@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- Memory usage of representors is huge when number of representor grows, + because PMD always allocate mbuf for each descriptor of Rx queue. + Polling the large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors in same switch domain. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ`` + is present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of shared Rx queue can return + packets of all ports in group, port ID is saved in ``mbuf.port``. + Basic SR-IOV ------------
lib/ethdev/rte_ethdev.c +1 -0
@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STR
lib/ethdev/rte_ethdev.h +7 -0
@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1373,6 +1374,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in group can be used to receive packets. +* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \
Signature · 1 line
2.33.0
Quoted 12 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.
Quoted 6 lines
Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Can you clarify this a little more?
Apologies if this was already covered:
* Can't we do this for Tx also?
Couple of nits inline. Thanks
Quoted 54 lines
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 5 files changed, 30 insertions(+)doc/guides/nics/features.rst +11
-0@@ -624,6 +624,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +0
-0
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 130
Quoted 8 lines
doc/guides/prog_guide/switch_representation.rst +5
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- Memory usage of representors is huge when number of representor grows, + because PMD always allocate mbuf for each descriptor of Rx queue. + Polling the large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors in same switch domain. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ``
"in the same switch"
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 133
Quoted 3 lines
doc/guides/prog_guide/switch_representation.rst +3
-0+ is present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of shared Rx queue can return
"of the shared Rx queue.."
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 134
Quoted 1 line
doc/guides/prog_guide/switch_representation.rst +1
-0+ packets of all ports in group, port ID is saved in ``mbuf.port``.
"ports in the group, "
Quoted 29 lines
doc/guides/prog_guide/switch_representation.rst +1
-0+ Basic SR-IOV ------------lib/ethdev/rte_ethdev.c +1
-0@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +1
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1379
Quoted 6 lines
lib/ethdev/rte_ethdev.h +3
-0@@ -1373,6 +1374,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in group can be used to receive packets.
"Any port in the group can"
Quoted 9 lines
lib/ethdev/rte_ethdev.h +3
-1+* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.33.0
Quoted 13 lines · Ajit Khaparde
Quoted 12 lines · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.
Quoted 7 lines
Quoted 6 lines
Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
Can you clarify this a little more?
Thanks for the review!
By using group ID, user can specify for example:
group 0: port 0-3, 2 queues per port, poll on core 0 and 1 group 1: port 4-127, 1 queue per port, poll on core 1.
Normally used for QoS and load balance.
Quoted 3 lines
Apologies if this was already covered:
* Can't we do this for Tx also?
Rx queue pre-fill mbufs for each queue, which consuming huge mbufs by default, most of them are less active, saving memory is the primary motatation for this feature.
Tx queue doesn't consume any mbuf by default until starting tx, no strong reason so far.
Quoted 125 lines
Couple of nits inline. Thanks
Quoted 54 lines
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 5 files changed, 30 insertions(+)doc/guides/nics/features.rst +11
-0@@ -624,6 +624,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +0
-0doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 130
Quoted 8 lines
doc/guides/prog_guide/switch_representation.rst +5
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- Memory usage of representors is huge when number of representor grows, + because PMD always allocate mbuf for each descriptor of Rx queue. + Polling the large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors in same switch domain. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ``"in the same switch"
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 133
Quoted 3 lines
doc/guides/prog_guide/switch_representation.rst +3
-0+ is present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of shared Rx queue can return"of the shared Rx queue.."
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 134
Quoted 1 line
doc/guides/prog_guide/switch_representation.rst +1
-0+ packets of all ports in group, port ID is saved in ``mbuf.port``."ports in the group, "
Quoted 29 lines
doc/guides/prog_guide/switch_representation.rst +1
-0+ Basic SR-IOV ------------lib/ethdev/rte_ethdev.c +1
-0@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +1
-0@@ -1047,6 +1047,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1379
Quoted 6 lines
lib/ethdev/rte_ethdev.h +3
-0@@ -1373,6 +1374,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in group can be used to receive packets. "Any port in the group can"
Quoted 9 lines
lib/ethdev/rte_ethdev.h +3
-1+* Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \ --2.33.0
PATCH v3 2/8 ethdev: new API to aggregate shared Rx queue group
In reply to Xueming LiThis patch introduces new api to aggreated ports among same shared Rx queue group. Only queues with specified share group is aggregated. Rx burst and device close are expected to be supported by new device.
--- lib/ethdev/ethdev_driver.h | 23 ++++++++++++++++++++++- lib/ethdev/rte_ethdev.c | 22 ++++++++++++++++++++++ lib/ethdev/rte_ethdev.h | 16 ++++++++++++++++ lib/ethdev/version.map | 3 +++ 4 files changed, 63 insertions(+), 1 deletion(-)
lib/ethdev/ethdev_driver.h +22 -1
@@ -786,10 +786,28 @@ typedef int (*eth_get_monitor_addr_t)(void *rxq,* @return * Negative errno value on error, number of info entries otherwise. */ -typedef int (*eth_representor_info_get_t )(struct rte_eth_dev *dev,struct rte_eth_representor_info *info); +/** +* @internal +* Aggregate shared Rx queue. +* +* Create a new port used for shared Rx queue polling. +* +* Only queues with specified share group are aggregated. +* At least Rx burst and device close should be supported. +* +* @param dev +* Ethdev handle of port. +* @param group +* Shared Rx queue group to aggregate. +* @return +* UINT16_MAX if failed, otherwise aggregated port number. +*/ +typedef int (*eth_shared_rxq_aggregate_t )(struct rte_eth_dev *dev, +uint32_t group); +/** * @internal A structure containing the functions exported by an Ethernet driver. */
@@ -950,6 +968,9 @@ struct eth_dev_ops {eth_representor_info_get_t representor_info_get;/**< Get representor info. */ + +eth_shared_rxq_aggregate_t shared_rxq_aggregate; +/**< Aggregate shared Rx queue. */ };/**
lib/ethdev/rte_ethdev.c +22 -0
@@ -6301,6 +6301,28 @@ rte_eth_representor_info_get(uint16_t port_id,return eth_err (port_id, (*dev->dev_ops->representor_info_get)(dev, info)); } +uint16_t +rte_eth_shared_rxq_aggregate (uint16_t port_id,uint32_t group) +{ +struct rte_eth_dev *dev; +uint64_t offloads; + +RTE_ETH_VALID_PORTID_OR_ERR_RET (port_id, -ENODEV ); + dev = &rte_eth_devices[port_id]; + +RTE_FUNC_PTR_OR_ERR_RET (*dev->dev_ops->shared_rxq_aggregate, +UINT16_MAX ); + + offloads = dev->data->dev_conf.rxmode.offloads; +if ((offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) ==0 ) { +RTE_ETHDEV_LOG (ERR ,"port_id=%u doesn't support Rx offload\n" , + port_id); +return UINT16_MAX ; + } + +return (*dev->dev_ops->shared_rxq_aggregate)(dev, group); +} +RTE_LOG_REGISTER_DEFAULT (rte_eth_dev_logtype,INFO );RTE_INIT (ethdev_init_telemetry)
lib/ethdev/rte_ethdev.h +16 -0
@@ -4895,6 +4895,22 @@ __rte_experimentalint rte_eth_representor_info_get (uint16_t port_id,struct rte_eth_representor_info *info); +/** +* Aggregate shared Rx queue ports to one port for polling. +* +* Only queues with specified share group is aggregated. +* Any operation besides Rx burst and device close is unexpected. +* +* @param port_id +* The port identifier of the device from shared Rx queue group. +* @param group +* Shared Rx queue group to aggregate. +* @return +* UINT16_MAX if failed, otherwise aggregated port number. +*/ +__rte_experimental +uint16_t rte_eth_shared_rxq_aggregate(uint16_t port_id, uint32_t group); +#include <rte_ethdev_core.h> /**
lib/ethdev/version.map +3 -0
@@ -249,6 +249,9 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_eth_shared_rxq_aggregate; }; INTERNAL {
Signature · 1 line
2.33.0
Re: [dpdk-dev] [PATCH v3 2/8] ethdev: new API to aggregate shared Rx queue group
Quoted 2 lines · Xueming Li
This patch introduces new api to aggreated ports among same shared Rx
s/aggregated/aggregate
Quoted 1 line
queue group. Only queues with specified share group is aggregated.
s/is/are
Quoted 3 lines
Rx burst and device close are expected to be supported by new device.
Signed-off-by Xueming Li <[email protected]>
Minor nits - typos actually!
Quoted 89 lines
--- lib/ethdev/ethdev_driver.h | 23 ++++++++++++++++++++++- lib/ethdev/rte_ethdev.c | 22 ++++++++++++++++++++++ lib/ethdev/rte_ethdev.h | 16 ++++++++++++++++ lib/ethdev/version.map | 3 +++ 4 files changed, 63 insertions(+), 1 deletion(-)lib/ethdev/ethdev_driver.h +22
-1@@ -786,10 +786,28 @@ typedef int (*eth_get_monitor_addr_t)(void *rxq,* @return * Negative errno value on error, number of info entries otherwise. */ -typedef int (*eth_representor_info_get_t )(struct rte_eth_dev *dev,struct rte_eth_representor_info *info); +/** +* @internal +* Aggregate shared Rx queue. +* +* Create a new port used for shared Rx queue polling. +* +* Only queues with specified share group are aggregated. +* At least Rx burst and device close should be supported. +* +* @param dev +* Ethdev handle of port. +* @param group +* Shared Rx queue group to aggregate. +* @return +* UINT16_MAX if failed, otherwise aggregated port number. +*/ +typedef int (*eth_shared_rxq_aggregate_t )(struct rte_eth_dev *dev, +uint32_t group); +/** * @internal A structure containing the functions exported by an Ethernet driver. */ @@ -950,6 +968,9 @@ struct eth_dev_ops {eth_representor_info_get_t representor_info_get;/**< Get representor info. */ + +eth_shared_rxq_aggregate_t shared_rxq_aggregate; +/**< Aggregate shared Rx queue. */ };/** lib/ethdev/rte_ethdev.c +22
-0@@ -6301,6 +6301,28 @@ rte_eth_representor_info_get(uint16_t port_id,return eth_err (port_id, (*dev->dev_ops->representor_info_get)(dev, info)); } +uint16_t +rte_eth_shared_rxq_aggregate (uint16_t port_id,uint32_t group) +{ +struct rte_eth_dev *dev; +uint64_t offloads; + +RTE_ETH_VALID_PORTID_OR_ERR_RET (port_id, -ENODEV ); + dev = &rte_eth_devices[port_id]; + +RTE_FUNC_PTR_OR_ERR_RET (*dev->dev_ops->shared_rxq_aggregate, +UINT16_MAX ); + + offloads = dev->data->dev_conf.rxmode.offloads; +if ((offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) ==0 ) { +RTE_ETHDEV_LOG (ERR ,"port_id=%u doesn't support Rx offload\n" , + port_id); +return UINT16_MAX ; + } + +return (*dev->dev_ops->shared_rxq_aggregate)(dev, group); +} +RTE_LOG_REGISTER_DEFAULT (rte_eth_dev_logtype,INFO );RTE_INIT (ethdev_init_telemetry)lib/ethdev/rte_ethdev.h +0
-0
lib/ethdev/rte_ethdev.h __rte_experimental · line 4901
Quoted 7 lines
lib/ethdev/rte_ethdev.h +4
-0@@ -4895,6 +4895,22 @@ __rte_experimentalint rte_eth_representor_info_get (uint16_t port_id,struct rte_eth_representor_info *info); +/** +* Aggregate shared Rx queue ports to one port for polling. +* +* Only queues with specified share group is aggregated.
s/is/are
Quoted 32 lines
lib/ethdev/rte_ethdev.h +12
-0+* Any operation besides Rx burst and device close is unexpected. +* +* @param port_id +* The port identifier of the device from shared Rx queue group. +* @param group +* Shared Rx queue group to aggregate. +* @return +* UINT16_MAX if failed, otherwise aggregated port number. +*/ +__rte_experimental +uint16_t rte_eth_shared_rxq_aggregate(uint16_t port_id, uint32_t group); +#include <rte_ethdev_core.h> /** lib/ethdev/version.map +3
-1@@ -249,6 +249,9 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_eth_shared_rxq_aggregate; }; INTERNAL { --2.33.0
PATCH v3 3/8 app/testpmd: dump port and queue info for each packet
In reply to Xueming LiIn case of shared Rx queue, port number of mbufs returned from one rx burst could be different.
To support shared Rx queue, this patch dumps mbuf->port and queue for each packet.
--- app/test-pmd/util.c | 1 + 1 file changed, 1 insertion(+)
app/test-pmd/util.c +1 -0
@@ -100,6 +100,7 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v3 4/8 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share" parameter to enable shared rxq for each rxq.
Default shared rxq group 0 is used, RX queues in same switch domain shares same rxq according to queue index.
Shared Rx queue is enabled only if device support offloading flag RTE_ETH_RX_OFFLOAD_SHARED_RXQ.
--- app/test-pmd/config.c | 6 +++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 18 ++++++++++++++++++ app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 5 +++++ 5 files changed, 43 insertions(+), 1 deletion(-)
app/test-pmd/config.c +5 -1
@@ -2707,7 +2707,11 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) +printf (" share group=%u" , + rx_conf->shared_group); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 0, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +18 -0
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -1506,6 +1511,11 @@ init_config_port_offloads(portid_t pid, uint32_t socket_id) port->dev_conf.txmode.offloads &= ~DEV_TX_OFFLOAD_MBUF_FAST_FREE ; +if (rxq_share >0 && + (port->dev_info.rx_offload_capa &RTE_ETH_RX_OFFLOAD_SHARED_RXQ )) + port->dev_conf.rxmode.offloads |= +RTE_ETH_RX_OFFLOAD_SHARED_RXQ ; +/* Apply Rx offloads configuration */ for (i =0 ; i < port->dev_info.max_rx_queues; i++) port->rx_conf[i].offloads = port->dev_conf.rxmode.offloads;
@@ -3401,6 +3411,14 @@ rxtx_port_config(struct rte_port *port)for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.rx_offload_capa & +RTE_ETH_RX_OFFLOAD_SHARED_RXQ )) { + offloads |=RTE_ETH_RX_OFFLOAD_SHARED_RXQ ; + port->rx_conf[qid].shared_group = nb_ports / rxq_share; + } +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +5 -0
@@ -389,6 +389,11 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create all queues in shared RX queue mode if device supports. + Group number grows per X ports, default to group 0 if X not specified. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v3 5/8 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared rxqs shares one set rx queue of groups zero. Shared Rx queue must must be polled from one core.
Checks and stops forwarding if shared rxq being scheduled on multiple cores.
--- app/test-pmd/config.c | 96 ++++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 101 insertions(+), 1 deletion(-)
app/test-pmd/config.c +96 -0
@@ -2883,6 +2883,102 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,portid_t src_port, +queueid_t src_rxq,lcoreid_t src_lc, +uint32_t shared_group) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((rxq_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (fs->rx_queue != src_rxq) +continue ; +if (rxq_conf->shared_group != shared_group) +continue ; +printf ("Shared RX queue group %u can't be scheduled on different cores:\n" , + shared_group); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf (" please use --nb-cores=%hu to limit forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((rxq_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, fs->rx_port, + fs->rx_queue, lc_id, + rxq_conf->shared_group)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2241,10 +2241,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v3 6/8 app/testpmd: add common fwd wrapper
In reply to Xueming LiFrom: Xiaoyu Min <[email protected]>
Added common forwarding wrapper function for all fwd engines which do the following in common:
- record core cycles
- call rte_eth_rx_burst(...,nb_pkt_per_burst)
- update received packets
- handle received mbufs with callback function
For better performance, the function is defined as macro.
--- app/test-pmd/5tswap.c | 25 +++++-------------------- app/test-pmd/csumonly.c | 25 ++++++------------------- app/test-pmd/flowgen.c | 20 +++++--------------- app/test-pmd/icmpecho.c | 30 ++++++++---------------------- app/test-pmd/iofwd.c | 24 +++++------------------- app/test-pmd/macfwd.c | 24 +++++------------------- app/test-pmd/macswap.c | 23 +++++------------------ app/test-pmd/rxonly.c | 32 ++++++++------------------------ app/test-pmd/testpmd.h | 19 +++++++++++++++++++ 9 files changed, 66 insertions(+), 156 deletions(-)
app/test-pmd/5tswap.c +5 -20
@@ -82,18 +82,16 @@ swap_udp(struct rte_udp_hdr *udp_hdr)* Parses each layer and swaps it. When the next layer doesn't match it stops. */ static void -pkt_burst_5tuple_swap (struct fwd_stream *fs) +_5tuple_swap_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_port *txp;struct rte_mbuf *mb;uint16_t next_proto;uint64_t ol_flags;uint16_t proto; -uint16_t nb_rx;uint16_t nb_tx;uint32_t retry; -int i;union {struct rte_ether_hdr *eth;
@@ -105,20 +103,6 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)uint8_t *byte; } h; -uint64_t start_tsc =0 ; - -get_start_cycles (&start_tsc); - -/* -* Receive a burst of packets and forward them. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; txp = &ports[fs->tx_port]; ol_flags =ol_flags_init (txp->dev_conf.txmode.offloads); vlan_qinq_set(pkts_burst, nb_rx, ol_flags,
@@ -182,12 +166,13 @@ pkt_burst_5tuple_swap(struct fwd_stream *fs)rte_pktmbuf_free (pkts_burst[nb_tx]); }while (++nb_tx < nb_rx); } -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (_5tuple_swap_stream); +struct fwd_engine five_tuple_swap_fwd_engine = { .fwd_mode_name ="5tswap" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_5tuple_swap, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/csumonly.c +6 -19
@@ -763,7 +763,7 @@ pkt_copy_split(const struct rte_mbuf *pkt) }/* -* Receive a burst of packets, and for each packet: +* For each packet in received mbuf: * - parse packet, and try to recognize a supported packet type (1) * - if it's not a supported packet type, don't touch the packet, else: * - reprocess the checksum of all supported layers. This is done in SW
@@ -792,9 +792,9 @@ pkt_copy_split(const struct rte_mbuf *pkt)* OUTER_IP is only useful for tunnel packets. */ static void -pkt_burst_checksum_forward (struct fwd_stream *fs) +checksum_forward_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_mbuf *gso_segments[GSO_MAX_PKT_BURST ];struct rte_gso_ctx *gso_ctx;struct rte_mbuf **tx_pkts_burst;
@@ -805,7 +805,6 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)void **gro_ctx;uint16_t gro_pkts_num;uint8_t gro_enable; -uint16_t nb_rx;uint16_t nb_tx;uint16_t nb_prep;uint16_t i;
@@ -820,18 +819,6 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)uint16_t nb_segments =0 ;int ret; -uint64_t start_tsc =0 ; - -get_start_cycles (&start_tsc); - -/* receive a burst of packet */ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; rx_bad_ip_csum =0 ; rx_bad_l4_csum =0 ; rx_bad_outer_l4_csum =0 ;
@@ -1138,13 +1125,13 @@ pkt_burst_checksum_forward(struct fwd_stream *fs)rte_pktmbuf_free (tx_pkts_burst[nb_tx]); }while (++nb_tx < nb_rx); } - -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (checksum_forward_stream); +struct fwd_engine csum_fwd_engine = { .fwd_mode_name ="csum" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_checksum_forward, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/flowgen.c +5 -15
@@ -61,10 +61,10 @@ RTE_DEFINE_PER_LCORE(int, _next_flow);* still do so in order to maintain traffic statistics. */ static void -pkt_burst_flow_gen (struct fwd_stream *fs) +flow_gen_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) {unsigned pkt_size = tx_pkt_length -4 ;/* Adjust FCS */ -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_mempool *mbp;struct rte_mbuf *pkt =NULL ;struct rte_ether_hdr *eth_hdr;
@@ -72,7 +72,6 @@ pkt_burst_flow_gen(struct fwd_stream *fs)struct rte_udp_hdr *udp_hdr;uint16_t vlan_tci, vlan_tci_outer;uint64_t ol_flags =0 ; -uint16_t nb_rx;uint16_t nb_tx;uint16_t nb_dropped;uint16_t nb_pkt;
@@ -80,17 +79,9 @@ pkt_burst_flow_gen(struct fwd_stream *fs)uint16_t i;uint32_t retry;uint64_t tx_offloads; -uint64_t start_tsc =0 ;int next_flow =RTE_PER_LCORE (_next_flow); -get_start_cycles (&start_tsc); - -/* Receive a burst of packets and discard them. */ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst);inc_rx_burst_stats (fs, nb_rx); - fs->rx_packets += nb_rx; -for (i =0 ; i < nb_rx; i++)rte_pktmbuf_free (pkts_burst[i]);
@@ -195,12 +186,11 @@ pkt_burst_flow_gen(struct fwd_stream *fs)rte_pktmbuf_free (pkts_burst[nb_tx]); }while (++nb_tx < nb_pkt); } -RTE_PER_LCORE (_next_flow) = next_flow; - -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (flow_gen_stream); +static void flowgen_begin (portid_t pi) {
@@ -211,5 +201,5 @@ struct fwd_engine flow_gen_engine = { .fwd_mode_name = "flowgen", .port_fwd_begin = flowgen_begin, .port_fwd_end = NULL, - .packet_fwd = pkt_burst_flow_gen, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/icmpecho.c +8 -22
@@ -267,13 +267,13 @@ ipv4_hdr_cksum(struct rte_ipv4_hdr *ip_h) (((rte_be_to_cpu_32 ((ipv4_addr)) >>24 ) &0x000000FF ) ==0xE0 )/* -* Receive a burst of packets, lookup for ICMP echo requests, and, if any, -* send back ICMP echo replies. +* Lookup for ICMP echo requests in received mbuf and, if any, +* send back ICMP echo replies to corresponding Tx port. */static void -reply_to_icmp_echo_rqsts (struct fwd_stream *fs) +reply_to_icmp_echo_rqsts_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_mbuf *pkt;struct rte_ether_hdr *eth_h;struct rte_vlan_hdr *vlan_h;
@@ -283,7 +283,6 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)struct rte_ether_addr eth_addr;uint32_t retry;uint32_t ip_addr; -uint16_t nb_rx;uint16_t nb_tx;uint16_t nb_replies;uint16_t eth_type;
@@ -291,22 +290,9 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs)uint16_t arp_op;uint16_t arp_pro;uint32_t cksum; -uint8_t i; +uint16_t i;int l2_len; -uint64_t start_tsc =0 ; -get_start_cycles (&start_tsc); - -/* -* First, receive a burst of packets. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; nb_replies =0 ;for (i =0 ; i < nb_rx; i++) {if (likely (i < nb_rx -1 ))
@@ -509,13 +495,13 @@ reply_to_icmp_echo_rqsts(struct fwd_stream *fs) }while (++nb_tx < nb_replies); } } - -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (reply_to_icmp_echo_rqsts_stream); +struct fwd_engine icmp_echo_engine = { .fwd_mode_name ="icmpecho" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = reply_to_icmp_echo_rqsts, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/iofwd.c +5 -19
@@ -44,25 +44,11 @@* to packets data. */ static void -pkt_burst_io_forward (struct fwd_stream *fs) +io_forward_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ]; -uint16_t nb_rx;uint16_t nb_tx;uint32_t retry; -uint64_t start_tsc =0 ; - -get_start_cycles (&start_tsc); - -/* -* Receive a burst of packets and forward them. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, - pkts_burst, nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - fs->rx_packets += nb_rx; nb_tx =rte_eth_tx_burst (fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
@@ -85,13 +71,13 @@ pkt_burst_io_forward(struct fwd_stream *fs)rte_pktmbuf_free (pkts_burst[nb_tx]); }while (++nb_tx < nb_rx); } - -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (io_forward_stream); +struct fwd_engine io_fwd_engine = { .fwd_mode_name ="io" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_io_forward, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/macfwd.c +5 -19
@@ -44,32 +44,18 @@* before forwarding them. */ static void -pkt_burst_mac_forward (struct fwd_stream *fs) +mac_forward_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_port *txp;struct rte_mbuf *mb;struct rte_ether_hdr *eth_hdr;uint32_t retry; -uint16_t nb_rx;uint16_t nb_tx;uint16_t i;uint64_t ol_flags =0 ;uint64_t tx_offloads; -uint64_t start_tsc =0 ; -get_start_cycles (&start_tsc); - -/* -* Receive a burst of packets and forward them. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; txp = &ports[fs->tx_port]; tx_offloads = txp->dev_conf.txmode.offloads;if (tx_offloads &DEV_TX_OFFLOAD_VLAN_INSERT )
@@ -116,13 +102,13 @@ pkt_burst_mac_forward(struct fwd_stream *fs)rte_pktmbuf_free (pkts_burst[nb_tx]); }while (++nb_tx < nb_rx); } - -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (mac_forward_stream); +struct fwd_engine mac_fwd_engine = { .fwd_mode_name ="mac" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_mac_forward, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/macswap.c +5 -18
@@ -50,27 +50,13 @@* addresses of packets before forwarding them. */ static void -pkt_burst_mac_swap (struct fwd_stream *fs) +mac_swap_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ];struct rte_port *txp; -uint16_t nb_rx;uint16_t nb_tx;uint32_t retry; -uint64_t start_tsc =0 ; -get_start_cycles (&start_tsc); - -/* -* Receive a burst of packets and forward them. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; txp = &ports[fs->tx_port];do_macswap (pkts_burst, nb_rx, txp);
@@ -95,12 +81,13 @@ pkt_burst_mac_swap(struct fwd_stream *fs)rte_pktmbuf_free (pkts_burst[nb_tx]); }while (++nb_tx < nb_rx); } -get_end_cycles (fs, start_tsc); } +PKT_BURST_FWD (mac_swap_stream); +struct fwd_engine mac_swap_engine = { .fwd_mode_name ="macswap" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_mac_swap, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/rxonly.c +8 -24
@@ -41,37 +41,21 @@#include "testpmd.h" /* -* Received a burst of packets. +* Process a burst of received packets from same stream. */ static void -pkt_burst_receive (struct fwd_stream *fs) +rxonly_forward_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst) { -struct rte_mbuf *pkts_burst[MAX_PKT_BURST ]; -uint16_t nb_rx; -uint16_t i; -uint64_t start_tsc =0 ; - -get_start_cycles (&start_tsc); - -/* -* Receive a burst of packets. -*/ - nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, pkts_burst, - nb_pkt_per_burst); -inc_rx_burst_stats (fs, nb_rx); -if (unlikely (nb_rx ==0 )) -return ; - - fs->rx_packets += nb_rx; -for (i =0 ; i < nb_rx; i++) -rte_pktmbuf_free (pkts_burst[i]); - -get_end_cycles (fs, start_tsc); +RTE_SET_USED (fs); +rte_pktmbuf_free_bulk (pkts_burst, nb_rx); } +PKT_BURST_FWD (rxonly_forward_stream) + struct fwd_engine rx_only_engine = { .fwd_mode_name ="rxonly" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_receive, + .packet_fwd = pkt_burst_fwd, };
app/test-pmd/testpmd.h +19 -0
@@ -1028,6 +1028,25 @@ void add_tx_dynf_callback(portid_t portid);void remove_tx_dynf_callback (portid_t portid);int update_jumbo_frame_offload (portid_t portid); +#define PKT_BURST_FWD (cb) \ +static void \ +pkt_burst_fwd(struct fwd_stream *fs) \ +{ \ + struct rte_mbuf *pkts_burst[nb_pkt_per_burst]; \ + uint16_t nb_rx; \ + uint64_t start_tsc = 0; \ + \ + get_start_cycles(&start_tsc); \ + nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, \ + pkts_burst, nb_pkt_per_burst); \ + inc_rx_burst_stats(fs, nb_rx); \ + if (unlikely(nb_rx == 0)) \ + return; \ + fs->rx_packets += nb_rx; \ + cb(fs, nb_rx, pkts_burst); \ + get_end_cycles(fs, start_tsc); \ +} +/* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function.
Signature · 1 line
2.33.0
Re: [dpdk-dev] [PATCH v3 6/8] app/testpmd: add common fwd wrapper
Quoted 32 lines · Xueming Li
From: Xiaoyu Min <[email protected]>
Added common forwarding wrapper function for all fwd engines which do the following in common:
- record core cycles
- callrte_eth_rx_burst(...,nb_pkt_per_burst)
- update received packets
- handle received mbufs with callback functionFor better performance, the function is defined as macro.
Signed-off-by Xiaoyu Min <[email protected]>Signed-off-by Xueming Li <[email protected]>--- app/test-pmd/5tswap.c | 25 +++++-------------------- app/test-pmd/csumonly.c | 25 ++++++------------------- app/test-pmd/flowgen.c | 20 +++++--------------- app/test-pmd/icmpecho.c | 30 ++++++++---------------------- app/test-pmd/iofwd.c | 24 +++++------------------- app/test-pmd/macfwd.c | 24 +++++------------------- app/test-pmd/macswap.c | 23 +++++------------------ app/test-pmd/rxonly.c | 32 ++++++++------------------------ app/test-pmd/testpmd.h | 19 +++++++++++++++++++ 9 files changed, 66 insertions(+), 156 deletions(-)app/test-pmd/5tswap.c +0
-0
app/test-pmd/5tswap.c swap_udp(struct rte_udp_hdr *udp_hdr) · line 85
Quoted 4 lines
app/test-pmd/5tswap.c +1
-0@@ -82,18 +82,16 @@ swap_udp(struct rte_udp_hdr *udp_hdr)* Parses each layer and swaps it. When the next layer doesn't match it stops. */ +PKT_BURST_FWD (_5tuple_swap_stream);
Please make _5tuple_swap_stream aka "cb" as inline function to make sure compiler doesn't generate yet another function pointer.
app/test-pmd/5tswap.c swap_udp(struct rte_udp_hdr *udp_hdr) · line 89
Quoted 5 lines
app/test-pmd/5tswap.c +0
-1struct fwd_engine mac_swap_engine = { .fwd_mode_name ="macswap" , .port_fwd_begin =NULL , .port_fwd_end =NULL , - .packet_fwd = pkt_burst_mac_swap,
See below
app/test-pmd/5tswap.c swap_udp(struct rte_udp_hdr *udp_hdr) · line 92
Quoted 3 lines
app/test-pmd/5tswap.c +2
-0+ .packet_fwd = pkt_burst_fwd, +#define PKT_BURST_FWD (cb) \
Probably it can pass prefix too like PKT_BURST_FWD(cb, prefix) to make a unique function and call PKT_BURST_FWD(_5tuple_swap_stream, mac_swap) for better readability
and avoid diff above section.
app/test-pmd/5tswap.c swap_udp(struct rte_udp_hdr *udp_hdr) · line 94
Quoted 2 lines
app/test-pmd/5tswap.c +2
-0+static void \ +pkt_burst_fwd (struct fwd_stream *fs)
pkt_burst_fwd##prefix(struct fwd_stream *fs)
\
Quoted 22 lines
app/test-pmd/5tswap.c +16
-1+{ \ +struct rte_mbuf *pkts_burst[nb_pkt_per_burst]; \ +uint16_t nb_rx; \ +uint64_t start_tsc =0 ; \ + \ +get_start_cycles (&start_tsc); \ + nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, \ + pkts_burst, nb_pkt_per_burst); \ +inc_rx_burst_stats (fs, nb_rx); \ +if (unlikely (nb_rx ==0 )) \ +return ; \ + fs->rx_packets += nb_rx; \ +cb (fs, nb_rx, pkts_burst); \ +get_end_cycles (fs, start_tsc); \ +} +/* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. -- 2.33.0
PATCH v3 7/8 app/testpmd: improve forwarding cache miss
In reply to Xueming LiTo minimize cache miss, adds flags and burst size used in forwarding to stream, moves condition tests in forwarding to flags in stream.
--- app/test-pmd/config.c | 18 ++++++++++++++---- app/test-pmd/flowgen.c | 6 +++--- app/test-pmd/noisy_vnf.c | 2 +- app/test-pmd/testpmd.h | 21 ++++++++++++--------- app/test-pmd/txonly.c | 8 ++++---- 5 files changed, 34 insertions(+), 21 deletions(-)
app/test-pmd/config.c +14 -4
@@ -3050,6 +3050,16 @@ fwd_topology_tx_port_get(portid_t rxp) } } +static void +fwd_stream_set_common (struct fwd_stream *fs) +{ + fs->nb_pkt_per_burst = nb_pkt_per_burst; + fs->record_burst_stats = !!record_burst_stats; + fs->record_core_cycles = !!record_core_cycles; + fs->retry_enabled = !!retry_enabled; + fs->rxq_share = !!rxq_share; +} +static void simple_fwd_config_setup (void ) {
@@ -3079,7 +3089,7 @@ simple_fwd_config_setup(void) fwd_ports_ids[fwd_topology_tx_port_get (i)]; fwd_streams[i]->tx_queue =0 ; fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port; - fwd_streams[i]->retry_enabled = retry_enabled; +fwd_stream_set_common (fwd_streams[i]); } }
@@ -3140,7 +3150,7 @@ rss_fwd_config_setup(void) fs->tx_port = fwd_ports_ids[txp]; fs->tx_queue = rxq; fs->peer_addr = fs->tx_port; - fs->retry_enabled = retry_enabled; +fwd_stream_set_common (fs); rxp++;if (rxp < nb_fwd_ports)continue ;
@@ -3255,7 +3265,7 @@ dcb_fwd_config_setup(void) fs->tx_port = fwd_ports_ids[txp]; fs->tx_queue = txq + j % nb_tx_queue; fs->peer_addr = fs->tx_port; - fs->retry_enabled = retry_enabled; +fwd_stream_set_common (fs); } fwd_lcores[lc_id]->stream_nb += rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
@@ -3326,7 +3336,7 @@ icmp_echo_config_setup(void) fs->tx_port = fs->rx_port; fs->tx_queue = rxq; fs->peer_addr = fs->tx_port; - fs->retry_enabled = retry_enabled; +fwd_stream_set_common (fs);if (verbose_level >0 ) printf(" stream=%d port=%d rxq=%d txq=%d\n", sm_id, fs->rx_port, fs->rx_queue,
app/test-pmd/flowgen.c +3 -3
@@ -97,12 +97,12 @@ flow_gen_stream(struct fwd_stream *fs, uint16_t nb_rx,if (tx_offloads &DEV_TX_OFFLOAD_MACSEC_INSERT ) ol_flags |=PKT_TX_MACSEC ; -for (nb_pkt =0 ; nb_pkt < nb_pkt_per_burst; nb_pkt++) { +for (nb_pkt =0 ; nb_pkt < fs->nb_pkt_per_burst; nb_pkt++) {if (!nb_pkt || !nb_clones) { nb_clones = nb_pkt_flowgen_clones;/* Logic limitation */ -if (nb_clones > nb_pkt_per_burst) - nb_clones = nb_pkt_per_burst; +if (nb_clones > fs->nb_pkt_per_burst) + nb_clones = fs->nb_pkt_per_burst; pkt =rte_mbuf_raw_alloc (mbp);if (!pkt)
app/test-pmd/noisy_vnf.c +1 -1
@@ -153,7 +153,7 @@ pkt_burst_noisy_vnf(struct fwd_stream *fs)uint64_t now; nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, - pkts_burst, nb_pkt_per_burst); + pkts_burst, fs->nb_pkt_per_burst);inc_rx_burst_stats (fs, nb_rx);if (unlikely (nb_rx ==0 )) goto flush;
app/test-pmd/testpmd.h +12 -9
@@ -128,12 +128,17 @@ struct fwd_stream {queueid_t tx_queue;/**< TX queue to send forwarded packets */ streamid_t peer_addr;/**< index of peer ethernet address of packets */ -unsigned int retry_enabled; +uint16_t nb_pkt_per_burst; + unsigned int record_burst_stats:1; + unsigned int record_core_cycles:1; + unsigned int retry_enabled:1; + unsigned int rxq_share:1;/* "read-write" results */ uint64_t rx_packets;/**< received packets */ uint64_t tx_packets;/**< received packets transmitted */ uint64_t fwd_dropped;/**< received packets not forwarded */ +uint64_t core_cycles;/**< used for RX and TX processing */ uint64_t rx_bad_ip_csum ;/**< received packets has bad ip checksum */ uint64_t rx_bad_l4_csum ;/**< received packets has bad l4 checksum */ uint64_t rx_bad_outer_l4_csum;
@@ -141,7 +146,6 @@ struct fwd_stream {uint64_t rx_bad_outer_ip_csum;/**< received packets having bad outer ip checksum */ unsigned int gro_times;/**< GRO operation times */ -uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats;struct fwd_lcore *lcore;/**< Lcore being scheduled. */
@@ -750,28 +754,27 @@ port_pci_reg_write(struct rte_port *port, uint32_t reg_off, uint32_t reg_v)static inline void get_start_cycles (uint64_t *start_tsc) { -if (record_core_cycles) - *start_tsc =rte_rdtsc (); + *start_tsc =rte_rdtsc (); }static inline void get_end_cycles (struct fwd_stream *fs,uint64_t start_tsc) { -if (record_core_cycles) +if (unlikely (fs->record_core_cycles)) fs->core_cycles +=rte_rdtsc () - start_tsc; }static inline void inc_rx_burst_stats (struct fwd_stream *fs,uint16_t nb_rx) { -if (record_burst_stats) +if (unlikely (fs->record_burst_stats)) fs->rx_burst_stats.pkt_burst_spread[nb_rx]++; }static inline void inc_tx_burst_stats (struct fwd_stream *fs,uint16_t nb_tx) { -if (record_burst_stats) +if (unlikely (fs->record_burst_stats)) fs->tx_burst_stats.pkt_burst_spread[nb_tx]++; }
@@ -1032,13 +1035,13 @@ int update_jumbo_frame_offload(portid_t portid);static void \pkt_burst_fwd (struct fwd_stream *fs) \ { \ -struct rte_mbuf *pkts_burst[nb_pkt_per_burst]; \ +struct rte_mbuf *pkts_burst[fs->nb_pkt_per_burst]; \uint16_t nb_rx; \uint64_t start_tsc =0 ; \ \get_start_cycles (&start_tsc); \ nb_rx =rte_eth_rx_burst (fs->rx_port, fs->rx_queue, \ - pkts_burst, nb_pkt_per_burst); \ + pkts_burst, fs->nb_pkt_per_burst); \inc_rx_burst_stats (fs, nb_rx); \if (unlikely (nb_rx ==0 )) \return ; \
app/test-pmd/txonly.c +4 -4
@@ -367,8 +367,8 @@ pkt_burst_transmit(struct fwd_stream *fs) eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); if (rte_mempool_get_bulk(mbp, (void **)pkts_burst, - nb_pkt_per_burst) == 0) { - for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) { + fs->nb_pkt_per_burst) == 0) { + for (nb_pkt = 0; nb_pkt < fs->nb_pkt_per_burst; nb_pkt++) { if (unlikely(!pkt_burst_prepare(pkts_burst[nb_pkt], mbp, ð_hdr, vlan_tci, vlan_tci_outer,
@@ -376,12 +376,12 @@ pkt_burst_transmit(struct fwd_stream *fs) nb_pkt, fs))) {rte_mempool_put_bulk (mbp, (void **)&pkts_burst[nb_pkt], - nb_pkt_per_burst - nb_pkt); + fs->nb_pkt_per_burst - nb_pkt);break ; } } }else { -for (nb_pkt =0 ; nb_pkt < nb_pkt_per_burst; nb_pkt++) { +for (nb_pkt =0 ; nb_pkt < fs->nb_pkt_per_burst; nb_pkt++) { pkt =rte_mbuf_raw_alloc (mbp);if (pkt ==NULL )break ;
Signature · 1 line
2.33.0
PATCH v3 8/8 app/testpmd: support shared Rx queue forwarding
In reply to Xueming LiBy enabling shared Rx queue, received packets come from all member ports in same shared Rx queue.
This patch adds a common forwarding function for shared Rx queue, groups source forwarding stream by looking into local streams on current lcore with packet source port(mbuf->port) and queue, then invokes callback to handle received packets for each source stream.
--- app/test-pmd/ieee1588fwd.c | 30 +++++++++++------ app/test-pmd/testpmd.c | 69 ++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 9 ++++- 3 files changed, 97 insertions(+), 11 deletions(-)
app/test-pmd/ieee1588fwd.c +20 -10
@@ -90,23 +90,17 @@ port_ieee1588_tx_timestamp_check(portid_t pi) }static void -ieee1588_packet_fwd (struct fwd_stream *fs) +ieee1588_fwd_stream (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkt) { -struct rte_mbuf *mb; +struct rte_mbuf *mb = (*pkt);struct rte_ether_hdr *eth_hdr;struct rte_ether_addr addr;struct ptpv2_msg *ptp_hdr;uint16_t eth_type;uint32_t timesync_index; -/* -* Receive 1 packet at a time. -*/ -if (rte_eth_rx_burst (fs->rx_port, fs->rx_queue, &mb,1 ) ==0 ) -return ; - - fs->rx_packets +=1 ; - +RTE_SET_USED (nb_rx);/* * Check that the received packet is a PTP packet that was detected * by the hardware.
@@ -198,6 +192,22 @@ ieee1588_packet_fwd(struct fwd_stream *fs)port_ieee1588_tx_timestamp_check (fs->rx_port); } +/* +* Wrapper of real fwd ingine. +*/ +static void +ieee1588_packet_fwd (struct fwd_stream *fs) +{ +struct rte_mbuf *mb; + +if (rte_eth_rx_burst (fs->rx_port, fs->rx_queue, &mb,1 ) ==0 ) +return ; +if (unlikely (fs->rxq_share >0 )) +forward_shared_rxq (fs,1 , &mb, ieee1588_fwd_stream); +else +ieee1588_fwd_stream (fs,1 , &mb); +} +static void port_ieee1588_fwd_begin (portid_t pi) {
app/test-pmd/testpmd.c +69 -0
75 lines not on this page · raw message
app/test-pmd/testpmd.h +8 -1
@@ -276,6 +276,8 @@ struct fwd_lcore {typedef void (*port_fwd_begin_t )(portid_t pi);typedef void (*port_fwd_end_t )(portid_t pi);typedef void (*packet_fwd_t )(struct fwd_stream *fs); +typedef void (*packet_fwd_cb )(struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts);struct fwd_engine {const char *fwd_mode_name;/**< Forwarding mode name. */
@@ -910,6 +912,8 @@ char *list_pkt_forwarding_modes(void);char *list_pkt_forwarding_retry_modes (void );void set_pkt_forwarding_mode (const char *fwd_mode);void start_packet_forwarding (int with_tx_first); +void forward_shared_rxq (struct fwd_stream *fs,uint16_t nb_rx, +struct rte_mbuf **pkts_burst,packet_fwd_cb fwd);void fwd_stats_display (void );void fwd_stats_reset (void );void stop_packet_forwarding (void );
@@ -1046,7 +1050,10 @@ pkt_burst_fwd(struct fwd_stream *fs) \if (unlikely (nb_rx ==0 )) \return ; \ fs->rx_packets += nb_rx; \ -cb (fs, nb_rx, pkts_burst); \ +if (fs->rxq_share) \ +forward_shared_rxq (fs, nb_rx, pkts_burst, cb); \ +else \ +cb (fs, nb_rx, pkts_burst); \get_end_cycles (fs, start_tsc); \ }
Signature · 1 line
2.33.0
v4 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggerate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
Xueming Li (6):
ethdev: introduce shared Rx queue
ethdev: new API to aggregate shared Rx queue group app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 102 +++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 23 ++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 11 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 ++ doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/ethdev_driver.h | 23 ++- lib/ethdev/rte_ethdev.c | 23 +++ lib/ethdev/rte_ethdev.h | 23 +++ lib/ethdev/version.map | 3 + 16 files changed, 398 insertions(+), 4 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v4 1/6 ethdev: introduce shared Rx queue
In current DPDK framework, each RX queue is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
This patch introduces shared RX queue. Ports with same configuration in a switch domain could share RX queue set by specifying sharing group. Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by mbuf->port.
Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
Multiple groups is supported by group ID.
---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html
--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 5 files changed, 30 insertions(+)
doc/guides/nics/features.rst +11 -0
@@ -626,6 +626,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +10 -0
@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- Memory usage of representors is huge when number of representor grows, + because PMD always allocate mbuf for each descriptor of Rx queue. + Polling the large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors in same switch. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ`` is + present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of the shared Rx queue can return + packets of all ports in the group, port ID is saved in ``mbuf.port``. + Basic SR-IOV ------------
lib/ethdev/rte_ethdev.c +1 -0
@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STR
lib/ethdev/rte_ethdev.h +7 -0
@@ -1077,6 +1077,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1403,6 +1404,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in the group can be used to receive +* packets. Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \
Signature · 1 line
2.33.0
Quoted 1 line · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for
RX -> Rx
Quoted 4 lines
incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
It should be highlighted that it is a problem of some PMDs. Not all.
Quoted 2 lines
This patch introduces shared RX queue. Ports with same configuration in
"This patch introduces" -> "Introduce"
RX -> Rx
Quoted 1 line
a switch domain could share RX queue set by specifying sharing group.
RX -> Rx
Quoted 1 line
Polling any queue using same shared RX queue receives packets from all
RX -> Rx
Quoted 6 lines
member ports. Source port is identified by
mbuf->port.Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
RX -> Rx
Quoted 2 lines
Multiple groups is supported by group ID.
is -> are
Quoted 3 lines
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>
The patch should update release notes.
Quoted 51 lines
---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 5 files changed, 30 insertions(+)doc/guides/nics/features.rst +11
-0@@ -626,6 +626,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +0
-0
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 127
Quoted 5 lines
doc/guides/prog_guide/switch_representation.rst +2
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- Memory usage of representors is huge when number of representor grows, + because PMD always allocate mbuf for each descriptor of Rx queue.
It is a problem of some PMDs only. So, it must be rewritten to highlight it.
Quoted 39 lines
doc/guides/prog_guide/switch_representation.rst +8
-0+ Polling the large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors in same switch. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ`` is + present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of the shared Rx queue can return + packets of all ports in the group, port ID is saved in ``mbuf.port``. + Basic SR-IOV ------------lib/ethdev/rte_ethdev.c +1
-0@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +1
-0@@ -1077,6 +1077,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1403,6 +1404,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000
lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1415
Quoted 10 lines
lib/ethdev/rte_ethdev.h +6
-0#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in the group can be used to receive +* packets. Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \
IMHO it should be squashed with the second patch to make it easier to review. Otherwise it is hard to understand what is shared_group and the offlaod which are dead in the patch.
Quoted 154 lines · Andrew Rybchenko
Quoted 1 line · Xueming Li
In current DPDK framework, each RX queue is pre-loaded with mbufs for
RX -> Rx
Quoted 4 lines
incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Most important, polling all ports leads to high cache miss, high latency and low throughput.
It should be highlighted that it is a problem of some PMDs. Not all.
Quoted 2 lines
This patch introduces shared RX queue. Ports with same configuration in
"This patch introduces" -> "Introduce"
RX -> Rx
Quoted 1 line
a switch domain could share RX queue set by specifying sharing group.
RX -> Rx
Quoted 1 line
Polling any queue using same shared RX queue receives packets from all
RX -> Rx
Quoted 6 lines
member ports. Source port is identified by
mbuf->port.Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share RX queue must be polled on single thread or core.
RX -> Rx
Quoted 2 lines
Multiple groups is supported by group ID.
is -> are
Quoted 3 lines
Signed-off-by Xueming Li <[email protected]>Cc Jerin Jacob <[email protected]>The patch should update release notes.
Quoted 51 lines
---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 5 files changed, 30 insertions(+)doc/guides/nics/features.rst +11
-0@@ -626,6 +626,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +0
-0doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 127
Quoted 5 lines
doc/guides/prog_guide/switch_representation.rst +2
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- Memory usage of representors is huge when number of representor grows, + because PMD always allocate mbuf for each descriptor of Rx queue.It is a problem of some PMDs only. So, it must be rewritten to highlight it.
Quoted 46 lines
doc/guides/prog_guide/switch_representation.rst +8
-0+ Polling the large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors in same switch. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ`` is + present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of the shared Rx queue can return + packets of all ports in the group, port ID is saved in ``mbuf.port``. + Basic SR-IOV ------------lib/ethdev/rte_ethdev.c +1
-0@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STRlib/ethdev/rte_ethdev.h +7
-0@@ -1077,6 +1077,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1403,6 +1404,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in the group can be used to receive +* packets. Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000
Quoted 7 lines
lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1415
Quoted 3 lines
lib/ethdev/rte_ethdev.h +0
-0#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \IMHO it should be squashed with the second patch to make it easier to review. Otherwise it is hard to understand what is
shared_groupand the offlaod which are dead in the patch.
Hi Andrew,
Thanks for the review! With discussion with Jerin, we want to drop second patch and decide how to aggregate ports later by collecting more feedback and idea. To make the offload and group clear, I'll add an example in commit message. v5 sent w/o seeing your another review on 0/6, please ignore for now.
PATCH v4 2/6 ethdev: new API to aggregate shared Rx queue group
In reply to Xueming LiThis patch introduces new api to aggreate ports among same shared Rx queue group. Only queues with specified share group are aggregated. Rx burst and device close are expected to be supported by new device.
--- lib/ethdev/ethdev_driver.h | 23 ++++++++++++++++++++++- lib/ethdev/rte_ethdev.c | 22 ++++++++++++++++++++++ lib/ethdev/rte_ethdev.h | 16 ++++++++++++++++ lib/ethdev/version.map | 3 +++ 4 files changed, 63 insertions(+), 1 deletion(-)
lib/ethdev/ethdev_driver.h +22 -1
@@ -782,10 +782,28 @@ typedef int (*eth_get_monitor_addr_t)(void *rxq,* @return * Negative errno value on error, number of info entries otherwise. */ -typedef int (*eth_representor_info_get_t )(struct rte_eth_dev *dev,struct rte_eth_representor_info *info); +/** +* @internal +* Aggregate shared Rx queue. +* +* Create a new port used for shared Rx queue polling. +* +* Only queues with specified share group are aggregated. +* At least Rx burst and device close should be supported. +* +* @param dev +* Ethdev handle of port. +* @param group +* Shared Rx queue group to aggregate. +* @return +* UINT16_MAX if failed, otherwise aggregated port number. +*/ +typedef uint16_t (*eth_shared_rxq_aggregate_t )(struct rte_eth_dev *dev, +uint32_t group); +/** * @internal A structure containing the functions exported by an Ethernet driver. */
@@ -946,6 +964,9 @@ struct eth_dev_ops {eth_representor_info_get_t representor_info_get;/**< Get representor info. */ + +eth_shared_rxq_aggregate_t shared_rxq_aggregate; +/**< Aggregate shared Rx queue. */ };/**
lib/ethdev/rte_ethdev.c +22 -0
@@ -6297,6 +6297,28 @@ rte_eth_representor_info_get(uint16_t port_id,return eth_err (port_id, (*dev->dev_ops->representor_info_get)(dev, info)); } +uint16_t +rte_eth_shared_rxq_aggregate (uint16_t port_id,uint32_t group) +{ +struct rte_eth_dev *dev; +uint64_t offloads; + +RTE_ETH_VALID_PORTID_OR_ERR_RET (port_id, -ENODEV ); + dev = &rte_eth_devices[port_id]; + +RTE_FUNC_PTR_OR_ERR_RET (*dev->dev_ops->shared_rxq_aggregate, +UINT16_MAX ); + + offloads = dev->data->dev_conf.rxmode.offloads; +if ((offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) ==0 ) { +RTE_ETHDEV_LOG (ERR ,"port_id=%u doesn't support Rx offload\n" , + port_id); +return UINT16_MAX ; + } + +return (*dev->dev_ops->shared_rxq_aggregate)(dev, group); +} +RTE_LOG_REGISTER_DEFAULT (rte_eth_dev_logtype,INFO );RTE_INIT (ethdev_init_telemetry)
lib/ethdev/rte_ethdev.h +16 -0
@@ -4909,6 +4909,22 @@ __rte_experimentalint rte_eth_representor_info_get (uint16_t port_id,struct rte_eth_representor_info *info); +/** +* Aggregate shared Rx queue ports to one port for polling. +* +* Only queues with specified share group are aggregated. +* Any operation besides Rx burst and device close is unexpected. +* +* @param port_id +* The port identifier of the device from shared Rx queue group. +* @param group +* Shared Rx queue group to aggregate. +* @return +* UINT16_MAX if failed, otherwise aggregated port number. +*/ +__rte_experimental +uint16_t rte_eth_shared_rxq_aggregate(uint16_t port_id, uint32_t group); +#include <rte_ethdev_core.h> /**
lib/ethdev/version.map +3 -0
@@ -247,6 +247,9 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_eth_shared_rxq_aggregate; }; INTERNAL {
Signature · 1 line
2.33.0
PATCH v4 3/6 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share" parameter to enable shared rxq for each rxq.
Default shared rxq group 0 is used, RX queues in same switch domain shares same rxq according to queue index.
Shared Rx queue is enabled only if device support offloading flag RTE_ETH_RX_OFFLOAD_SHARED_RXQ.
--- app/test-pmd/config.c | 6 +++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 18 ++++++++++++++++++ app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 45 insertions(+), 1 deletion(-)
app/test-pmd/config.c +5 -1
@@ -2709,7 +2709,11 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) +printf (" share group=%u" , + rx_conf->shared_group); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +18 -0
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -1506,6 +1511,11 @@ init_config_port_offloads(portid_t pid, uint32_t socket_id) port->dev_conf.txmode.offloads &= ~DEV_TX_OFFLOAD_MBUF_FAST_FREE ; +if (rxq_share >0 && + (port->dev_info.rx_offload_capa &RTE_ETH_RX_OFFLOAD_SHARED_RXQ )) + port->dev_conf.rxmode.offloads |= +RTE_ETH_RX_OFFLOAD_SHARED_RXQ ; +/* Apply Rx offloads configuration */ for (i =0 ; i < port->dev_info.max_rx_queues; i++) port->rx_conf[i].offloads = port->dev_conf.rxmode.offloads;
@@ -3401,6 +3411,14 @@ rxtx_port_config(struct rte_port *port)for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.rx_offload_capa & +RTE_ETH_RX_OFFLOAD_SHARED_RXQ )) { + offloads |=RTE_ETH_RX_OFFLOAD_SHARED_RXQ ; + port->rx_conf[qid].shared_group = nb_ports / rxq_share; + } +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared RX queue mode if device supports. + Group number grows per X ports, default to group 0 if X not specified. + Only "shared-rxq" forwarding engine suppose to resolve source stream + correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v4 4/6 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v4 5/6 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared rxqs shares one set rx queue of groups zero. Shared Rx queue must must be polled from one core.
Checks and stops forwarding if shared rxq being scheduled on multiple cores.
--- app/test-pmd/config.c | 96 ++++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 101 insertions(+), 1 deletion(-)
app/test-pmd/config.c +96 -0
@@ -2885,6 +2885,102 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,portid_t src_port, +queueid_t src_rxq,lcoreid_t src_lc, +uint32_t shared_group) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((rxq_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (fs->rx_queue != src_rxq) +continue ; +if (rxq_conf->shared_group != shared_group) +continue ; +printf ("Shared RX queue group %u can't be scheduled on different cores:\n" , + shared_group); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf (" please use --nb-cores=%hu to limit forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((rxq_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, fs->rx_port, + fs->rx_queue, lc_id, + rxq_conf->shared_group)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2241,10 +2241,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v4 6/6 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accrodingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
1. We need extra flag in dev_info->dev_capa RTE_ETH_DEV_CAPA_RX_SHARE to advertise that the device supports Rx sharing.
2. I think we need "rx_domain" in device info (which should be treated in boundaries of the switch_domain) if and only if RTE_ETH_DEV_CAPA_RX_SHARE is advertised. Otherwise rx_domain value does not make sense.
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with mbuf->port filled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat used port_id as an input port_id, but always check mbuf->port for each packet.
4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.
Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.
PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 11 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capa could be used here, no?
Quoted 6 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.
I see, this will give flexibility of different hw, will add it.
Quoted 14 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.
Quoted 12 lines
4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.
RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Quoted 3 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
Quoted 6 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Quoted 146 lines · Xueming Li
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set
mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 11 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capacould be used here, no?Quoted 6 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.I see, this will give flexibility of different hw, will add it.
Quoted 14 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.Quoted 12 lines
4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Quoted 15 lines
Quoted 3 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
Quoted 6 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Hi Andrew,
I realized that we are talking different things, this feature introduced 2 RxQ share:
1. Share mempool to save memory
2. Share polling to save latency
What you suggested is reuse all RxQ configuration IIUC, maybe we should break the flag into 3, so application could learn PMD capability and configure accordingly, how do you think? RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POOL RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POLL RTE_ETH_RX_OFFLOAD_RXQ_SHARE_CFG //implies POOL and POLL
Regards,
Xueming
Quoted 102 lines · Xueming(Steven) Li
Quoted 101 lines · Xueming Li
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set
mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 8 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capacould be used here, no?
It depends. But we definitely need a flag which says that below rx_domain makes sense. It could be either RTE_ETH_DEV_CAPA_RX_SHARE or an Rx offload capability.
The question is if it is really an offload. The offload is when something could be done by HW/FW and result is provided to SW. May be it is just a nit picking...
May be we don't need an offload at all. Just have RTE_ETH_DEV_CAPA_RXQ_SHARE and use non-zero group ID as a flag that an RxQ should be shared (zero - default, no sharing). ethdev layer may check consistency on its layer to ensure that the device capability is reported if non-zero group is specified on queue setup.
Quoted 37 lines
Quoted 37 lines
Quoted 7 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.I see, this will give flexibility of different hw, will add it.
Quoted 26 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.
Quoted 2 lines
Quoted 2 lines
RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Thinking a bit more about it I agree that RSS settings could be individual. Offload could be individual as well, but I'm not sure about all offloads. E.g. Rx scatter which is related to Rx buffer size (which is shared since Rx mempool is shared) vs MTU. May be it is acceptable. We just must define rules what should happen if offloads contradict to each other. It should be highlighted in the description including driver callback to ensure that PMD maintainers are responsible for consistency checks.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
I agree. The problem of many flexible solutions is complexity to support. We'll see how it goes.
Quoted 16 lines
Quoted 8 lines
Quoted 7 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Hi Andrew,
I realized that we are talking different things, this feature introduced 2 RxQ share:
1. Share mempool to save memory
2. Share polling to save latency
Quoted 4 lines
What you suggested is reuse all RxQ configuration IIUC, maybe we should break the flag into 3, so application could learn PMD capability and configure accordingly, how do you think?
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POOL
Not sure that I understand. Just specify the same mempool on Rx queue setup. Isn't it sufficient?
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POLL
It implies pool sharing if I'm not mistaken. Of course, we can pool many different HW queues in one poll, but it hardly makes sense to care specially about it. IMHO RxQ sharing is a sharing of the underlying HW Rx queue.
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_CFG//implies POOL and POLL
It is hardly a feature. Rather a possible limitation.
Andrew.
Quoted 213 lines · Andrew Rybchenko
Quoted 102 lines · Xueming(Steven) Li
Quoted 101 lines · Xueming Li
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set
mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 8 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capacould be used here, no?It depends. But we definitely need a flag which says that below
rx_domainmakes sense. It could be eitherRTE_ETH_DEV_CAPA_RX_SHAREor an Rx offload capability.The question is if it is really an offload. The offload is when something could be done by HW/FW and result is provided to SW. May be it is just a nit picking...
May be we don't need an offload at all. Just have
RTE_ETH_DEV_CAPA_RXQ_SHAREand use non-zero group ID as a flag that an RxQ should be shared (zero - default, no sharing). ethdev layer may check consistency on its layer to ensure that the device capability is reported if non-zero group is specified on queue setup.Quoted 37 lines
Quoted 37 lines
Quoted 7 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.I see, this will give flexibility of different hw, will add it.
Quoted 26 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.Quoted 2 lines
Quoted 2 lines
RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Thinking a bit more about it I agree that RSS settings could be individual. Offload could be individual as well, but I'm not sure about all offloads. E.g. Rx scatter which is related to Rx buffer size (which is shared since Rx mempool is shared) vs MTU. May be it is acceptable. We just must define rules what should happen if offloads contradict to each other. It should be highlighted in the description including driver callback to ensure that PMD maintainers are responsible for consistency checks.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
I agree. The problem of many flexible solutions is complexity to support. We'll see how it goes.
Quoted 16 lines
Quoted 8 lines
Quoted 7 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Hi Andrew,
I realized that we are talking different things, this feature introduced 2 RxQ share:
1. Share mempool to save memory
2. Share polling to save latencyQuoted 4 lines
What you suggested is reuse all RxQ configuration IIUC, maybe we should break the flag into 3, so application could learn PMD capability and configure accordingly, how do you think?
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POOLNot sure that I understand. Just specify the same mempool on Rx queue setup. Isn't it sufficient?
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POLL
Quoted 8 lines
It implies pool sharing if I'm not mistaken. Of course, we can pool many different HW queues in one poll, but it hardly makes sense to care specially about it. IMHO RxQ sharing is a sharing of the underlying HW Rx queue.
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_CFG//implies POOL and POLLIt is hardly a feature. Rather a possible limitation.
Thanks, then I'd drop this suggestion then.
Here is the TODO list, let me know if anything missing:
1. change offload flag to RTE_ETH_DEV_CAPA_RX_SHARE
2. RxQ share group check in ethdev
3. add rx_domain into device info
Quoted 2 lines
Andrew.
Quoted 219 lines · Xueming(Steven) Li
Quoted 218 lines · Andrew Rybchenko
Quoted 102 lines · Xueming(Steven) Li
Quoted 101 lines · Xueming Li
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set
mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 8 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capacould be used here, no?It depends. But we definitely need a flag which says that below
rx_domainmakes sense. It could be eitherRTE_ETH_DEV_CAPA_RX_SHAREor an Rx offload capability.The question is if it is really an offload. The offload is when something could be done by HW/FW and result is provided to SW. May be it is just a nit picking...
May be we don't need an offload at all. Just have
RTE_ETH_DEV_CAPA_RXQ_SHAREand use non-zero group ID as a flag that an RxQ should be shared (zero - default, no sharing). ethdev layer may check consistency on its layer to ensure that the device capability is reported if non-zero group is specified on queue setup.Quoted 37 lines
Quoted 37 lines
Quoted 7 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.I see, this will give flexibility of different hw, will add it.
Quoted 26 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.Quoted 2 lines
Quoted 2 lines
RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Thinking a bit more about it I agree that RSS settings could be individual. Offload could be individual as well, but I'm not sure about all offloads. E.g. Rx scatter which is related to Rx buffer size (which is shared since Rx mempool is shared) vs MTU. May be it is acceptable. We just must define rules what should happen if offloads contradict to each other. It should be highlighted in the description including driver callback to ensure that PMD maintainers are responsible for consistency checks.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
I agree. The problem of many flexible solutions is complexity to support. We'll see how it goes.
Quoted 16 lines
Quoted 8 lines
Quoted 7 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Hi Andrew,
I realized that we are talking different things, this feature introduced 2 RxQ share:
1. Share mempool to save memory
2. Share polling to save latencyQuoted 4 lines
What you suggested is reuse all RxQ configuration IIUC, maybe we should break the flag into 3, so application could learn PMD capability and configure accordingly, how do you think?
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POOLNot sure that I understand. Just specify the same mempool on Rx queue setup. Isn't it sufficient?
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POLLIt implies pool sharing if I'm not mistaken. Of course, we can pool many different HW queues in one poll, but it hardly makes sense to care specially about it. IMHO RxQ sharing is a sharing of the underlying HW Rx queue.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_CFG//implies POOL and POLLIt is hardly a feature. Rather a possible limitation.
Thanks, then I'd drop this suggestion then.
Here is the TODO list, let me know if anything missing:
1. change offload flag toRTE_ETH_DEV_CAPA_RX_SHARE
RTE_ETH_DEV_CAPA_RXQ_SHARE since it is not sharing of entire Rx, but just some queues.
Quoted 6 lines
2. RxQ share group check in ethdev
3. addrx_domaininto device infoQuoted 2 lines
Andrew.
Quoted 224 lines · Andrew Rybchenko
Quoted 223 lines · Xueming(Steven) Li
Quoted 221 lines · Andrew Rybchenko
Quoted 102 lines · Xueming(Steven) Li
Quoted 101 lines · Xueming Li
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set
mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 8 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capacould be used here, no?It depends. But we definitely need a flag which says that below
rx_domainmakes sense. It could be eitherRTE_ETH_DEV_CAPA_RX_SHAREor an Rx offload capability.The question is if it is really an offload. The offload is when something could be done by HW/FW and result is provided to SW. May be it is just a nit picking...
May be we don't need an offload at all. Just have
RTE_ETH_DEV_CAPA_RXQ_SHAREand use non-zero group ID as a flag that an RxQ should be shared (zero - default, no sharing). ethdev layer may check consistency on its layer to ensure that the device capability is reported if non-zero group is specified on queue setup.Quoted 37 lines
Quoted 37 lines
Quoted 7 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.I see, this will give flexibility of different hw, will add it.
Quoted 26 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.Quoted 2 lines
Quoted 2 lines
RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Thinking a bit more about it I agree that RSS settings could be individual. Offload could be individual as well, but I'm not sure about all offloads. E.g. Rx scatter which is related to Rx buffer size (which is shared since Rx mempool is shared) vs MTU. May be it is acceptable. We just must define rules what should happen if offloads contradict to each other. It should be highlighted in the description including driver callback to ensure that PMD maintainers are responsible for consistency checks.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
I agree. The problem of many flexible solutions is complexity to support. We'll see how it goes.
Quoted 16 lines
Quoted 8 lines
Quoted 7 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Hi Andrew,
I realized that we are talking different things, this feature introduced 2 RxQ share:
1. Share mempool to save memory
2. Share polling to save latencyQuoted 4 lines
What you suggested is reuse all RxQ configuration IIUC, maybe we should break the flag into 3, so application could learn PMD capability and configure accordingly, how do you think?
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POOLNot sure that I understand. Just specify the same mempool on Rx queue setup. Isn't it sufficient?
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POLLIt implies pool sharing if I'm not mistaken. Of course, we can pool many different HW queues in one poll, but it hardly makes sense to care specially about it. IMHO RxQ sharing is a sharing of the underlying HW Rx queue.
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_CFG//implies POOL and POLLIt is hardly a feature. Rather a possible limitation.
Quoted 7 lines
Quoted 4 lines
Thanks, then I'd drop this suggestion then.
Here is the TODO list, let me know if anything missing:
1. change offload flag toRTE_ETH_DEV_CAPA_RX_SHARE
RTE_ETH_DEV_CAPA_RXQ_SHAREsince it is not sharing of entire Rx, but just some queues.
OK
Quoted 3 lines
Quoted 3 lines
2. RxQ share group check in ethdev
3. addrx_domaininto device info
Seems rte_eth_switch_info is better palce for rx_domain.
Quoted 5 lines
Quoted 4 lines
Quoted 3 lines
Andrew.
Quoted 224 lines · Andrew Rybchenko
Quoted 223 lines · Xueming(Steven) Li
Quoted 221 lines · Andrew Rybchenko
Quoted 102 lines · Xueming(Steven) Li
Quoted 101 lines · Xueming Li
Quoted 32 lines · Andrew Rybchenko
Hi Xueming,
Quoted 29 lines · Xueming Li
In current DPDK framework, all RX queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared RX queue. PF and representors with same configuration in same switch domain could share RX queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared RX queue receives packets from all member ports. Source port is identified by
mbuf->port.Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of polling two share groups:
core group queue
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3Quoted 7 lines
Quoted 5 lines
Shared RX queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
I apologize that I jump in into the review process that late.
Appreciate the bold suggestion, never too late :)
Quoted 5 lines
Frankly speaking I doubt that it is the best design to solve the problem. Yes, I confirm that the problem exists, but I think there is better and simpler way to solve it.
Quoted 10 lines
The problem of the suggested solution is that it puts all the headache about consistency to application and PMDs without any help from ethdev layer to guarantee the consistency. As the result I believe it will be either missing/lost consistency checks or huge duplication in each PMD which supports the feature. Shared RxQs must be equally configured including number of queues, offloads (taking device level Rx offloads into account), RSS settings etc. So, applications must care about it and PMDs (or ethdev layer) must check it.
The name might be confusing, here is my understanding:
1. NIC shares the buffer supply HW Q between shared RxQs - for memory
2. PMD polls one shared RxQ - for latency and performance
3. Most per queue features like offloads and RSS not impacted. That's why this not mentioned. Some offloading might not being supported due to PMD or hw limitation, need to add check in PMD case by case.
4. Multiple group is defined for service level flexibility. For example, PF and VIP customer's load distributed via queues and dedicate cores. Low priority customers share one core with one shared queue. multiple groups enables more combination.
5. One port could assign queues to different group for polling flexibility. For example first 4 queues in group 0 and next 4 queues in group1, each group have other member ports with 4 queues, so the port with 8 queues could be polled with 8 cores w/o non-shared rxq penalty, in other words, each core only poll one shared RxQ.Quoted 8 lines
The advantage of the solution is that any device may create group and subsequent devices join. Absence of primary device is nice. But do we really need it? Will the design work if some representors are configured to use shared RxQ, but some do not? Theoretically it is possible, but could require extra non-trivial code on fast path.
If multiple groups, any device could be hot-unplugged.
Mixed configuration is supported, the only difference is how to set
mbuf->port. Since group is per queue, mixed is better to be supported, didn't see any difficulty here.PDM could select to support only group 0, same settings for each rxq, that fits most scenario.
Quoted 8 lines
Also looking at the first two patch I don't understand how application will find out which devices may share RxQs. E.g. if we have two difference NICs which support sharing, we can try to setup only one group 0, but finally will have two devices (not one) which must be polled.
Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
1. We need extra flag in
dev_info->dev_capaRTE_ETH_DEV_CAPA_RX_SHAREto advertise that the device supports Rx sharing.
dev_info->rx_queue_offload_capacould be used here, no?It depends. But we definitely need a flag which says that below
rx_domainmakes sense. It could be eitherRTE_ETH_DEV_CAPA_RX_SHAREor an Rx offload capability.The question is if it is really an offload. The offload is when something could be done by HW/FW and result is provided to SW. May be it is just a nit picking...
May be we don't need an offload at all. Just have
RTE_ETH_DEV_CAPA_RXQ_SHAREand use non-zero group ID as a flag that an RxQ should be shared (zero - default, no sharing). ethdev layer may check consistency on its layer to ensure that the device capability is reported if non-zero group is specified on queue setup.Quoted 37 lines
Quoted 37 lines
Quoted 7 lines
2. I think we need "
rx_domain" in device info (which should be treated in boundaries of theswitch_domain) if and only ifRTE_ETH_DEV_CAPA_RX_SHAREis advertised. Otherwiserx_domainvalue does not make sense.I see, this will give flexibility of different hw, will add it.
Quoted 26 lines
(1) and (2) will allow application to find out which devices can share Rx.
3. Primary device (representors backing device) should advertise shared RxQ offload. Enabling of the offload tells the device to provide packets to all device in the Rx domain with
mbuf->portfilled in appropriately. Also it allows app to identify primary device in the Rx domain. When application enables the offload, it must ensure that it does not treat usedport_idas an inputport_id, but always checkmbuf->portfor each packet.4. A new Rx mode should be introduced for secondary devices. It should not allow to configure RSS, specify any Rx offloads etc. ethdev must ensure it. It is an open question right now if it should require to provide primary
port_id. In theory representors have it. However, may be it is nice for consistency to ensure that application knows that it does. If shared Rx mode is specified for device, application does not need to setup RxQs and attempts to do it should be discarded in ethdev.
For consistency it is better to ensure that number of queues match.Quoted 2 lines
Quoted 2 lines
RSS and Rx offloads should be supported as individual, PMD needs to check if not supported.
Thinking a bit more about it I agree that RSS settings could be individual. Offload could be individual as well, but I'm not sure about all offloads. E.g. Rx scatter which is related to Rx buffer size (which is shared since Rx mempool is shared) vs MTU. May be it is acceptable. We just must define rules what should happen if offloads contradict to each other. It should be highlighted in the description including driver callback to ensure that PMD maintainers are responsible for consistency checks.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
It is an interesting question what should happen if primary device is reconfigured and shared Rx is disabled on reconfiguration.
I feel better no primary port/queue assumption in configuration, all members are equally treated, each queue can join or quit share group, that's important to support multiple groups.
I agree. The problem of many flexible solutions is complexity to support. We'll see how it goes.
Quoted 16 lines
Quoted 8 lines
Quoted 7 lines
5. If so, in theory implementation of the Rx burst in the secondary could simply call Rx burst on primary device.
Andrew.
Hi Andrew,
I realized that we are talking different things, this feature introduced 2 RxQ share:
1. Share mempool to save memory
2. Share polling to save latencyQuoted 4 lines
What you suggested is reuse all RxQ configuration IIUC, maybe we should break the flag into 3, so application could learn PMD capability and configure accordingly, how do you think?
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POOLNot sure that I understand. Just specify the same mempool on Rx queue setup. Isn't it sufficient?
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_POLLIt implies pool sharing if I'm not mistaken. Of course, we can pool many different HW queues in one poll, but it hardly makes sense to care specially about it. IMHO RxQ sharing is a sharing of the underlying HW Rx queue.
Quoted 1 line
RTE_ETH_RX_OFFLOAD_RXQ_SHARE_CFG//implies POOL and POLLIt is hardly a feature. Rather a possible limitation.
Quoted 7 lines
Quoted 4 lines
Thanks, then I'd drop this suggestion then.
Here is the TODO list, let me know if anything missing:
1. change offload flag toRTE_ETH_DEV_CAPA_RX_SHARE
RTE_ETH_DEV_CAPA_RXQ_SHAREsince it is not sharing of entire Rx, but just some queues.
V6 posted, thanks!
Quoted 8 lines
Quoted 7 lines
2. RxQ share group check in ethdev
3. addrx_domaininto device infoQuoted 2 lines
Andrew.
v5 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors with same configuration in same switch domain could share Rx queue set by specifying shared Rx queue offloading flag and sharing group.
All ports that Shared Rx queue actually shares One Rx queue and only pre-load mbufs to one Rx queue, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group0, 4 shared Rx queues per member port: PF, repr0, repr1 Group1, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
Xueming Li (5):
ethdev: introduce shared Rx queue app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 102 +++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 23 ++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 11 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 ++ doc/guides/rel_notes/release_21_11.rst | 4 + doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 + 15 files changed, 339 insertions(+), 3 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v5 1/5 ethdev: introduce shared Rx queue
In current DPDK framework, each Rx queue is pre-loaded with mbufs for incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports with same configuration in a switch domain could share Rx queue set by specifying sharing group. Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group.
Share Rx queue must be polled on single thread or core.
Multiple groups are supported by group ID.
Example grouping and polling model to reflect service priority:
Group0, 2 shared Rx queues per port: PF, rep0, rep1 Group1, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
---
Rx queue object could be used as shared Rx queue object, it's important to clear all queue control callback api that using queue object:
https://mails.dpdk.org/archives/dev/2021-July/215574.html
--- doc/guides/nics/features.rst | 11 +++++++++++ doc/guides/nics/features/default.ini | 1 + doc/guides/prog_guide/switch_representation.rst | 10 ++++++++++ doc/guides/rel_notes/release_21_11.rst | 4 ++++ lib/ethdev/rte_ethdev.c | 1 + lib/ethdev/rte_ethdev.h | 7 +++++++ 6 files changed, 34 insertions(+)
doc/guides/nics/features.rst +11 -0
@@ -626,6 +626,17 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same switch domain. + +* **[uses] rte_eth_rxconf,rte_eth_rxmode**: ``offloads:RTE_ETH_RX_OFFLOAD_SHARED_RXQ``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +10 -0
@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same switch. ``RTE_ETH_RX_OFFLOAD_SHARED_RXQ`` is + present in Rx offloading capability of device info. Setting the + offloading flag in device Rx mode or Rx queue configuration to enable + shared Rx queue. Polling any member port of the shared Rx queue can return + packets of all ports in the group, port ID is saved in ``mbuf.port``. + Basic SR-IOV ------------
doc/guides/rel_notes/release_21_11.rst +4 -0
@@ -134,6 +134,10 @@ New Features * Added tests to validate packets hard expiry. * Added tests to verify tunnel header verification in IPsec inbound. +* **Added ethdev shared Rx queue support. ** + + * Added new Rx queue offloading capability flag. + * Added share group to Rx queue configuration. Removed Items -------------
lib/ethdev/rte_ethdev.c +1 -0
@@ -127,6 +127,7 @@ static const struct {RTE_RX_OFFLOAD_BIT2STR (OUTER_UDP_CKSUM ),RTE_RX_OFFLOAD_BIT2STR (RSS_HASH ),RTE_ETH_RX_OFFLOAD_BIT2STR (BUFFER_SPLIT ), + RTE_ETH_RX_OFFLOAD_BIT2STR(SHARED_RXQ), };#undef RTE_RX_OFFLOAD_BIT2STR
lib/ethdev/rte_ethdev.h +7 -0
@@ -1077,6 +1077,7 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +uint32_t shared_group;/**< Shared port group index in switch domain. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1403,6 +1404,12 @@ struct rte_eth_conf {#define DEV_RX_OFFLOAD_OUTER_UDP_CKSUM 0x00040000#define DEV_RX_OFFLOAD_RSS_HASH 0x00080000#define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000 +/** +* Rx queue is shared among ports in same switch domain to save memory, +* avoid polling each port. Any port in the group can be used to receive +* packets. Real source port number saved in mbuf->port field. +*/ +#define RTE_ETH_RX_OFFLOAD_SHARED_RXQ 0x00200000#define DEV_RX_OFFLOAD_CHECKSUM (DEV_RX_OFFLOAD_IPV4_CKSUM | \ DEV_RX_OFFLOAD_UDP_CKSUM | \
Signature · 1 line
2.33.0
PATCH v5 2/5 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share" parameter to enable shared rxq for each rxq.
Default shared rxq group 0 is used, Rx queues in same switch domain shares same rxq according to queue index.
Shared Rx queue is enabled only if device support offloading flag RTE_ETH_RX_OFFLOAD_SHARED_RXQ.
--- app/test-pmd/config.c | 6 +++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 18 ++++++++++++++++++ app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 45 insertions(+), 1 deletion(-)
app/test-pmd/config.c +5 -1
@@ -2709,7 +2709,11 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) +printf (" share group=%u" , + rx_conf->shared_group); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +18 -0
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -1506,6 +1511,11 @@ init_config_port_offloads(portid_t pid, uint32_t socket_id) port->dev_conf.txmode.offloads &= ~DEV_TX_OFFLOAD_MBUF_FAST_FREE ; +if (rxq_share >0 && + (port->dev_info.rx_offload_capa &RTE_ETH_RX_OFFLOAD_SHARED_RXQ )) + port->dev_conf.rxmode.offloads |= +RTE_ETH_RX_OFFLOAD_SHARED_RXQ ; +/* Apply Rx offloads configuration */ for (i =0 ; i < port->dev_info.max_rx_queues; i++) port->rx_conf[i].offloads = port->dev_conf.rxmode.offloads;
@@ -3401,6 +3411,14 @@ rxtx_port_config(struct rte_port *port)for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.rx_offload_capa & +RTE_ETH_RX_OFFLOAD_SHARED_RXQ )) { + offloads |=RTE_ETH_RX_OFFLOAD_SHARED_RXQ ; + port->rx_conf[qid].shared_group = nb_ports / rxq_share; + } +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared Rx queue mode if device supports. + Group number grows per X ports, default to group 0 if X not specified. + Only "shared-rxq" forwarding engine suppose to resolve source stream + correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v5 3/5 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v5 4/5 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared rxqs shares one set rx queue of groups zero. Shared Rx queue must must be polled from one core.
Checks and stops forwarding if shared rxq being scheduled on multiple cores.
--- app/test-pmd/config.c | 96 ++++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 101 insertions(+), 1 deletion(-)
app/test-pmd/config.c +96 -0
@@ -2885,6 +2885,102 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,portid_t src_port, +queueid_t src_rxq,lcoreid_t src_lc, +uint32_t shared_group) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((rxq_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (fs->rx_queue != src_rxq) +continue ; +if (rxq_conf->shared_group != shared_group) +continue ; +printf ("Shared Rx queue group %u can't be scheduled on different cores:\n" , + shared_group); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf (" please use --nb-cores=%hu to limit forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((rxq_conf->offloads &RTE_ETH_RX_OFFLOAD_SHARED_RXQ ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, fs->rx_port, + fs->rx_queue, lc_id, + rxq_conf->shared_group)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2241,10 +2241,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v5 5/5 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accrodingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
v6 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors in same Rx domain and switch domain could share Rx queue set by specifying non-zero share group value in Rx queue configuration.
All ports that share Rx queue actually shares hardware descriptor queue and feed all Rx queues with one descriptor supply, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group1, 4 shared Rx queues per member port: PF, repr0, repr1 Group2, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
v6:
- replace RxQ offload flag with device offload capability flag
- add Rx domain
- RxQ is shared when share group > 0
- update testpmd accordingly
Xueming Li (5):
ethdev: introduce shared Rx queue app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 106 ++++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 17 +- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 13 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 ++ doc/guides/rel_notes/release_21_11.rst | 5 + doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 9 ++ lib/ethdev/rte_ethdev.h | 21 +++ 15 files changed, 362 insertions(+), 3 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v6 1/5 ethdev: introduce shared Rx queue
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by mbuf->port.
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported by non-zero share group ID. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Even Rx queue shared, queue configuration like offloads and RSS should not be impacted.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
PMD driver advertise shared Rx queue capability via RTE_ETH_DEV_CAPA_RXQ_SHARE.
PMD driver is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
--- doc/guides/nics/features.rst | 13 ++++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 +++++++++ doc/guides/rel_notes/release_21_11.rst | 5 +++++ lib/ethdev/rte_ethdev.c | 9 ++++++++ lib/ethdev/rte_ethdev.h | 21 +++++++++++++++++++ 6 files changed, 59 insertions(+)
doc/guides/nics/features.rst +13 -0
@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +10 -0
@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` is + present in device capability of device info. Setting non-zero share group + in Rx queue configuration to enable share. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------
doc/guides/rel_notes/release_21_11.rst +5 -0
@@ -141,6 +141,11 @@ New Features * Added tests to validate packets hard expiry. * Added tests to verify tunnel header verification in IPsec inbound. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. Removed Items -------------
lib/ethdev/rte_ethdev.c +9 -0
@@ -2159,6 +2159,15 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%u while device doesn't support Rx queue share in %s()\n" , + port_id, rx_queue_id, local_conf.share_group, + __func__); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device.
lib/ethdev/rte_ethdev.h +21 -0
@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid +* member port's configuration contradict to each other. +*/ +uint32_t share_group;/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1445,6 +1452,14 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* every port. Multiple groups is supported by share_group of Rx +* queue configuration. Polling any port in the group receive packets +* of all member ports, source port identified by mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE 0x00000004/**@}*/ /*
@@ -1488,6 +1503,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +uint16_t rx_domain; +/**< +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ };/**
Signature · 1 line
2.33.0
Quoted 10 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Quoted 8 lines
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by
mbuf->port.Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported by non-zero share group ID. Device
"by non-zero share group ID" is not required. Since it must be always non-zero to enable sharing.
Quoted 5 lines
should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Even Rx queue shared, queue configuration like offloads and RSS should not be impacted.
I don't understand above sentence.
Even when Rx queues are shared, queue configuration like offloads and RSS may differ. If a PMD has some limitation, it should care about consistency itself. These limitations should be documented in the PMD documentation.
Quoted 7 lines
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
Can I have:
PF RxQ#0, RxQ#1
Rep0 RxQ#0 shared with PF RxQ#0
Rep1 RxQ#0 shared with PF RxQ#1
I guess no, since it looks like RxQ ID must be equal. Or am I missing something? Otherwise grouping rules are not obvious to me. May be we need dedicated shared_qid in boundaries of the share_group?
Quoted 79 lines
PMD driver advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD driver is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
Signed-off-by Xueming Li <[email protected]>--- doc/guides/nics/features.rst | 13 ++++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 +++++++++ doc/guides/rel_notes/release_21_11.rst | 5 +++++ lib/ethdev/rte_ethdev.c | 9 ++++++++ lib/ethdev/rte_ethdev.h | 21 +++++++++++++++++++ 6 files changed, 59 insertions(+)doc/guides/nics/features.rst +13
-0@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +10
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` is + present in device capability of device info. Setting non-zero share group + in Rx queue configuration to enable share. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +0
-0
doc/guides/rel_notes/release_21_11.rst New Features · line 148
Quoted 8 lines
doc/guides/rel_notes/release_21_11.rst +5
-0@@ -141,6 +141,11 @@ New Features * Added tests to validate packets hard expiry. * Added tests to verify tunnel header verification in IPsec inbound. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine.
Please, add one more empty line since it must be two before the next section. Also it should be put after the last ethdev item above since list of features has defined order.
Quoted 8 lines
doc/guides/rel_notes/release_21_11.rst +0
-0Removed Items -------------lib/ethdev/rte_ethdev.c +0
-0
lib/ethdev/rte_ethdev.c rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id, · line 2167
Quoted 9 lines
lib/ethdev/rte_ethdev.c +6
-0@@ -2159,6 +2159,15 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%u while device doesn't support Rx queue share in %s()\n" , + port_id, rx_queue_id, local_conf.share_group, + __func__);
I'd remove function name logging here. Log is unique enough.
Quoted 11 lines
lib/ethdev/rte_ethdev.c +3
-0+return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device. lib/ethdev/rte_ethdev.h +0
-0
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1053
Quoted 10 lines
lib/ethdev/rte_ethdev.h +7
-0@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid +* member port's configuration contradict to each other. +*/ +uint32_t share_group;
I think that we don't need 32-bit for shared groups. 16-bits sounds more than enough.
Quoted 5 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1445,6 +1452,14 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001
lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1462
Quoted 10 lines
lib/ethdev/rte_ethdev.h +8
-0/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* every port. Multiple groups is supported by share_group of Rx +* queue configuration. Polling any port in the group receive packets +* of all member ports, source port identified by mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE 0x00000004
Let's use RTE_BIT64(2)
I think above two should be fixed in a separate cleanup patch.
lib/ethdev/rte_ethdev.h struct rte_eth_switch_info { · line 1511
Quoted 13 lines
lib/ethdev/rte_ethdev.h +6
-0/**@}*/ /* @@ -1488,6 +1503,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +uint16_t rx_domain; +/**< +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/
Please, put the documentation before the documented field.
[snip]
Quoted 26 lines · Andrew Rybchenko
Quoted 10 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Quoted 8 lines
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by
mbuf->port.Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported by non-zero share group ID. Device
"by non-zero share group ID" is not required. Since it must be always non-zero to enable sharing.
Quoted 3 lines
should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Quoted 9 lines
Quoted 2 lines
Even Rx queue shared, queue configuration like offloads and RSS should not be impacted.
I don't understand above sentence.
Even when Rx queues are shared, queue configuration like offloads and RSS may differ. If a PMD has some limitation, it should care about consistency itself. These limitations should be documented in the PMD documentation.
OK, I'll remove this line.
Quoted 14 lines
Quoted 7 lines
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0Can I have:
PF RxQ#0, RxQ#1
Rep0 RxQ#0 shared with PF RxQ#0
Rep1 RxQ#0 shared with PF RxQ#1
Quoted 4 lines
I guess no, since it looks like RxQ ID must be equal. Or am I missing something? Otherwise grouping rules are not obvious to me. May be we need dedicated
shared_qidin boundaries of theshare_group?
Yes, RxQ ID must be equal, following configuration should work:
Rep1 RxQ#1 shared with PF RxQ#1
Equal mapping should work by default instead of a new field that must be set. I'll add some description to emphasis, how do you think?
Quoted 157 lines
Quoted 80 lines
PMD driver advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD driver is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
Signed-off-by Xueming Li <[email protected]>--- doc/guides/nics/features.rst | 13 ++++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 +++++++++ doc/guides/rel_notes/release_21_11.rst | 5 +++++ lib/ethdev/rte_ethdev.c | 9 ++++++++ lib/ethdev/rte_ethdev.h | 21 +++++++++++++++++++ 6 files changed, 59 insertions(+)doc/guides/nics/features.rst +13
-0@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +10
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` is + present in device capability of device info. Setting non-zero share group + in Rx queue configuration to enable share. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +0
-0doc/guides/rel_notes/release_21_11.rst New Features · line 148
Quoted 8 lines
doc/guides/rel_notes/release_21_11.rst +5
-0@@ -141,6 +141,11 @@ New Features * Added tests to validate packets hard expiry. * Added tests to verify tunnel header verification in IPsec inbound. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine.Please, add one more empty line since it must be two before the next section. Also it should be put after the last ethdev item above since list of features has defined order.
Quoted 8 lines
doc/guides/rel_notes/release_21_11.rst +0
-0Removed Items -------------lib/ethdev/rte_ethdev.c +0
-0lib/ethdev/rte_ethdev.c rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id, · line 2167
Quoted 9 lines
lib/ethdev/rte_ethdev.c +6
-0@@ -2159,6 +2159,15 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%u while device doesn't support Rx queue share in %s()\n" , + port_id, rx_queue_id, local_conf.share_group, + __func__);I'd remove function name logging here. Log is unique enough.
Quoted 11 lines
lib/ethdev/rte_ethdev.c +3
-0+return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device. lib/ethdev/rte_ethdev.h +0
-0lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1053
Quoted 10 lines
lib/ethdev/rte_ethdev.h +7
-0@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid +* member port's configuration contradict to each other. +*/ +uint32_t share_group;I think that we don't need 32-bit for shared groups. 16-bits sounds more than enough.
Quoted 5 lines
lib/ethdev/rte_ethdev.h +0
-0/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1445,6 +1452,14 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1462
Quoted 10 lines
lib/ethdev/rte_ethdev.h +8
-0/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* every port. Multiple groups is supported by share_group of Rx +* queue configuration. Polling any port in the group receive packets +* of all member ports, source port identified by mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE 0x00000004Let's use
RTE_BIT64(2)
Quoted 2 lines
I think above two should be fixed in a separate cleanup patch.
Not only above two, more Rx/Tx offload bits to cleanup, let's do it later.
Quoted 19 lines
Quoted 5 lines
lib/ethdev/rte_ethdev.h +0
-0/**@}*/ /* lib/ethdev/rte_ethdev.h struct rte_eth_switch_info { · line 1511
Quoted 9 lines
lib/ethdev/rte_ethdev.h +6
-0@@ -1488,6 +1503,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +uint16_t rx_domain; +/**< +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ Please, put the documentation before the documented field.
[snip]
Quoted 53 lines · Xueming(Steven) Li
Quoted 26 lines · Andrew Rybchenko
Quoted 10 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Quoted 8 lines
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by
mbuf->port.Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported by non-zero share group ID. Device
"by non-zero share group ID" is not required. Since it must be always non-zero to enable sharing.
Quoted 3 lines
should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Quoted 9 lines
Quoted 2 lines
Even Rx queue shared, queue configuration like offloads and RSS should not be impacted.
I don't understand above sentence.
Even when Rx queues are shared, queue configuration like offloads and RSS may differ. If a PMD has some limitation, it should care about consistency itself. These limitations should be documented in the PMD documentation.OK, I'll remove this line.
Quoted 14 lines
Quoted 7 lines
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0Can I have:
PF RxQ#0, RxQ#1
Rep0 RxQ#0 shared with PF RxQ#0
Rep1 RxQ#0 shared with PF RxQ#1
Quoted 7 lines
Quoted 4 lines
I guess no, since it looks like RxQ ID must be equal. Or am I missing something? Otherwise grouping rules are not obvious to me. May be we need dedicated
shared_qidin boundaries of theshare_group?Yes, RxQ ID must be equal, following configuration should work:
Rep1 RxQ#1 shared with PF RxQ#1
But I want just one RxQ on Rep1. I don't need two.
Quoted 2 lines
Equal mapping should work by default instead of a new field that must be set. I'll add some description to emphasis, how do you think?
Sorry for delay with reply. I think that above limitation is not nice. It is better to avoid it.
[snip]
Quoted 62 lines · Andrew Rybchenko
Quoted 53 lines · Xueming(Steven) Li
Quoted 26 lines · Andrew Rybchenko
Quoted 10 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Quoted 8 lines
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by
mbuf->port.Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported by non-zero share group ID. Device
"by non-zero share group ID" is not required. Since it must be always non-zero to enable sharing.
Quoted 3 lines
should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Quoted 9 lines
Quoted 2 lines
Even Rx queue shared, queue configuration like offloads and RSS should not be impacted.
I don't understand above sentence.
Even when Rx queues are shared, queue configuration like offloads and RSS may differ. If a PMD has some limitation, it should care about consistency itself. These limitations should be documented in the PMD documentation.OK, I'll remove this line.
Quoted 14 lines
Quoted 7 lines
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0Can I have:
PF RxQ#0, RxQ#1
Rep0 RxQ#0 shared with PF RxQ#0
Rep1 RxQ#0 shared with PF RxQ#1Quoted 7 lines
Quoted 4 lines
I guess no, since it looks like RxQ ID must be equal. Or am I missing something? Otherwise grouping rules are not obvious to me. May be we need dedicated
shared_qidin boundaries of theshare_group?Yes, RxQ ID must be equal, following configuration should work:
Rep1 RxQ#1 shared with PF RxQ#1
Quoted 7 lines
But I want just one RxQ on Rep1. I don't need two.
Quoted 2 lines
Equal mapping should work by default instead of a new field that must be set. I'll add some description to emphasis, how do you think?
Sorry for delay with reply. I think that above limitation is not nice. It is better to avoid it.
Okay, it will offer more flexibility. I will add in next version. User has to be aware the indirect mapping relation, the following polling in above example rx burt the same shared RxQ:
PF RxQ#1
Rep1 RxQ#0 shared with PF RxQ#1
Quoted 2 lines
[snip]
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1050
Quoted 11 lines · Xueming Li
index
6d80514ba7a..041da6ee52f100644lib/ethdev/rte_ethdev.h +4
-0@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid
When you update the set, can you please update 'PMD driver' usage too?
PMD = Poll Mode Driver, so second 'driver' is duplicate, there are a few more instance of this usage in this set.
Quoted 15 lines · Ferruh Yigit
lib/ethdev/rte_ethdev.h struct rte_eth_rxconf { · line 1050
Quoted 11 lines · Xueming Li
index
6d80514ba7a..041da6ee52f100644lib/ethdev/rte_ethdev.h +4
-0@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid When you update the set, can you please update 'PMD driver' usage too?
Quoted 2 lines
PMD = Poll Mode Driver, so second 'driver' is duplicate, there are a few more instance of this usage in this set.
Got it, thanks!
BTW, PMD patches updated:
https://patches.dpdk.org/project/dpdk/list/?series=19709
PATCH v6 2/5 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share=X" parameter to enable shared RxQ, share if device supports, otherwise fallback to standard RxQ.
Share group number grows per X ports. X defaults to MAX, implies all ports join share group 1.
Forwarding engine "shared-rxq" should be used which Rx only and update stream statistics correctly.
--- app/test-pmd/config.c | 6 +++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 12 ++++++++++++ app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 39 insertions(+), 1 deletion(-)
app/test-pmd/config.c +5 -1
@@ -2709,7 +2709,11 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->share_group >0 ) +printf (" share group=%u" , + rx_conf->share_group); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +12 -0
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -3401,6 +3406,13 @@ rxtx_port_config(struct rte_port *port)for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE )) +/* Non-zero share group to enable RxQ share. */ + port->rx_conf[qid].share_group = nb_ports / rxq_share + +1 ; +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared Rx queue mode if device supports. + Group number grows per X ports. X defaults to MAX, implies all ports + join share group 1. Forwarding engine "shared-rxq" should be used + which Rx only and update stream statistics correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v6 3/5 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v6 4/5 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared Rx queue must be polled on same core. This patch checks and stops forwarding if shared RxQ being scheduled on multiple
cores.
It's suggested to use same number of Rx queues and polling cores.
--- app/test-pmd/config.c | 100 +++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 105 insertions(+), 1 deletion(-)
app/test-pmd/config.c +100 -0
@@ -2885,6 +2885,106 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,portid_t src_port, +queueid_t src_rxq,lcoreid_t src_lc, +uint32_t share_group) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (fs->rx_queue != src_rxq) +continue ; +if (rxq_conf->share_group != share_group) +continue ; +printf ("Shared Rx queue group %u can't be scheduled on different cores:\n" , + share_group); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf (" please use --nb-cores=%hu to limit forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, fs->rx_port, + fs->rx_queue, lc_id, + rxq_conf->share_group)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2236,10 +2236,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v6 5/5 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accordingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
v7 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors in same Rx domain and switch domain could share Rx queue set by specifying non-zero share group value in Rx queue configuration.
All ports that share Rx queue actually shares hardware descriptor queue and feed all Rx queues with one descriptor supply, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group1, 4 shared Rx queues per member port: PF, repr0, repr1 Group2, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
v6:
- replace RxQ offload flag with device offload capability flag
- add Rx domain
- RxQ is shared when share group > 0
- update testpmd accordingly
v7:
- fix testpmd share group id allocation
- change rx_domain to 16bits
Xueming Li (5):
ethdev: introduce shared Rx queue app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 106 ++++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 23 ++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 13 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 ++ doc/guides/rel_notes/release_21_11.rst | 6 + doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 8 + lib/ethdev/rte_ethdev.h | 21 +++ 15 files changed, 365 insertions(+), 6 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v7 1/5 ethdev: introduce shared Rx queue
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Port A RxQ X can share RxQ with Port B RxQ X, but can't share with RxQ Y. All member ports in share group share a list of shared Rx queue indexed by Rx queue ID.
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by mbuf->port.
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
PMD advertise shared Rx queue capability via RTE_ETH_DEV_CAPA_RXQ_SHARE.
PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
--- doc/guides/nics/features.rst | 13 ++++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 ++++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 21 +++++++++++++++++++ 6 files changed, 59 insertions(+)
doc/guides/nics/features.rst +13 -0
@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +10 -0
@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` is + present in device capability of device info. Setting non-zero share group + in Rx queue configuration to enable share. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------
doc/guides/rel_notes/release_21_11.rst +6 -0
@@ -67,6 +67,12 @@ New Features * Modified to allow ``--huge-dir`` option to specify a sub-directory within a hugetlbfs mountpoint. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 and
lib/ethdev/rte_ethdev.c +8 -0
@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device.
lib/ethdev/rte_ethdev.h +21 -0
@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid +* member port's configuration contradict to each other. +*/ +uint16_t share_group;/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1445,6 +1452,14 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* every port. Multiple groups is supported by share_group of Rx +* queue configuration. Polling any port in the group receive packets +* of all member ports, source port identified by mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /*
@@ -1488,6 +1503,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/**
Signature · 1 line
2.33.0
Quoted 11 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Quoted 7 lines
Port A RxQ X can share RxQ with Port B RxQ X, but can't share with RxQ Y. All member ports in share group share a list of shared Rx queue indexed by Rx queue ID.
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by
mbuf->port.
Is this port the physical port which received the packet?
Or does this port number correlate with the port_id seen by the application?
Quoted 3 lines
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
So it is upto the application to poll the queue of any member port or all ports or a designated port to handle Rx?
Quoted 168 lines
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0PMD advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
Signed-off-by Xueming Li <[email protected]>--- doc/guides/nics/features.rst | 13 ++++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 ++++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 21 +++++++++++++++++++ 6 files changed, 59 insertions(+)doc/guides/nics/features.rst +13
-0@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +10
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` is + present in device capability of device info. Setting non-zero share group + in Rx queue configuration to enable share. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +6
-0@@ -67,6 +67,12 @@ New Features * Modified to allow ``--huge-dir`` option to specify a sub-directory within a hugetlbfs mountpoint. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 andlib/ethdev/rte_ethdev.c +8
-0@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device. lib/ethdev/rte_ethdev.h +21
-1@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid +* member port's configuration contradict to each other. +*/ +uint16_t share_group;/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1445,6 +1452,14 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* every port. Multiple groups is supported by share_group of Rx +* queue configuration. Polling any port in the group receive packets +* of all member ports, source port identified by mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /* @@ -1488,6 +1503,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/** -- 2.33.0
Quoted 16 lines · Ajit Khaparde
Quoted 15 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Port A RxQ X can share RxQ with Port B RxQ X, but can't share with RxQ Y. All member ports in share group share a list of shared Rx queue indexed by Rx queue ID.
Quoted 5 lines
Quoted 3 lines
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, source port is identified by
mbuf->port.Is this port the physical port which received the packet?
Or does this port number correlate with theport_idseen by the application?
Hi Ajit,
It's the port_id of member ports - PF or representor port. I'll update commit message to avoid confusion.
Quoted 8 lines
Quoted 6 lines
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
So it is upto the application to poll the queue of any member port or all ports or a designated port to handle Rx?
Yes, up to application. As described in cover letter, aggregator port will be considered after collecting more suggestion and user feedback.
Quoted 169 lines
Quoted 169 lines
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0PMD advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
Signed-off-by Xueming Li <[email protected]>--- doc/guides/nics/features.rst | 13 ++++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 10 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 ++++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 21 +++++++++++++++++++ 6 files changed, 59 insertions(+)doc/guides/nics/features.rst +13
-0@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +10
-0@@ -123,6 +123,16 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` is + present in device capability of device info. Setting non-zero share group + in Rx queue configuration to enable share. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +6
-0@@ -67,6 +67,12 @@ New Features * Modified to allow ``--huge-dir`` option to specify a sub-directory within a hugetlbfs mountpoint. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 andlib/ethdev/rte_ethdev.c +8
-0@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device. lib/ethdev/rte_ethdev.h +21
-1@@ -1044,6 +1044,13 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD driver is responsible for Rx queue consistency checks to avoid +* member port's configuration contradict to each other. +*/ +uint16_t share_group;/** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa @@ -1445,6 +1452,14 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* every port. Multiple groups is supported by share_group of Rx +* queue configuration. Polling any port in the group receive packets +* of all member ports, source port identified by mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /* @@ -1488,6 +1503,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/** -- 2.33.0
PATCH v7 2/5 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share=X" parameter to enable shared RxQ, share if device supports, otherwise fallback to standard RxQ.
Share group number grows per X ports. X defaults to MAX, implies all ports join share group 1.
Forwarding engine "shared-rxq" should be used which Rx only and update stream statistics correctly.
--- app/test-pmd/config.c | 6 +++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 18 +++++++++++++++--- app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 42 insertions(+), 4 deletions(-)
app/test-pmd/config.c +5 -1
@@ -2709,7 +2709,11 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->share_group >0 ) +printf (" share group=%u" , + rx_conf->share_group); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +15 -3
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -3393,14 +3398,21 @@ dev_event_callback(const char *device_name, enum rte_dev_event_type type, }static void -rxtx_port_config (struct rte_port *port) +rxtx_port_config (portid_t pid) {uint16_t qid;uint64_t offloads; +struct rte_port *port = &ports[pid];for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE )) +/* Non-zero share group to enable RxQ share. */ + port->rx_conf[qid].share_group = pid / rxq_share +1 ; +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
@@ -3558,7 +3570,7 @@ init_port_config(void) port->dev_conf.rxmode.mq_mode =ETH_MQ_RX_NONE ; } -rxtx_port_config (port); +rxtx_port_config (pid); ret =eth_macaddr_get_print_err (pid, &port->eth_addr);if (ret !=0 )
@@ -3772,7 +3784,7 @@ init_port_dcb_config(portid_t pid,memcpy (&rte_port->dev_conf, &port_conf,sizeof (struct rte_eth_conf )); -rxtx_port_config (rte_port); +rxtx_port_config (pid);/* VLAN filter */ rte_port->dev_conf.rxmode.offloads |=DEV_RX_OFFLOAD_VLAN_FILTER ;for (i =0 ; i <RTE_DIM (vlan_tags); i++)
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared Rx queue mode if device supports. + Group number grows per X ports. X defaults to MAX, implies all ports + join share group 1. Forwarding engine "shared-rxq" should be used + which Rx only and update stream statistics correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v7 3/5 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v7 4/5 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared Rx queue must be polled on same core. This patch checks and stops forwarding if shared RxQ being scheduled on multiple
cores.
It's suggested to use same number of Rx queues and polling cores.
--- app/test-pmd/config.c | 100 +++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 105 insertions(+), 1 deletion(-)
app/test-pmd/config.c +100 -0
@@ -2885,6 +2885,106 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,portid_t src_port, +queueid_t src_rxq,lcoreid_t src_lc, +uint32_t share_group) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (fs->rx_queue != src_rxq) +continue ; +if (rxq_conf->share_group != share_group) +continue ; +printf ("Shared Rx queue group %u can't be scheduled on different cores:\n" , + share_group); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf (" please use --nb-cores=%hu to limit forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, fs->rx_port, + fs->rx_queue, lc_id, + rxq_conf->share_group)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2236,10 +2236,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v7 5/5 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accordingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
v8 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors in same Rx domain and switch domain could share Rx queue set by specifying non-zero share group value in Rx queue configuration.
All ports that share Rx queue actually shares hardware descriptor queue and feed all Rx queues with one descriptor supply, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group1, 4 shared Rx queues per member port: PF, repr0, repr1 Group2, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
v6:
- replace RxQ offload flag with device offload capability flag
- add Rx domain
- RxQ is shared when share group > 0
- update testpmd accordingly
v7:
- fix testpmd share group id allocation
- change rx_domain to 16bits
v8:
- add new patch for testpmd to show device Rx domain ID and capability
- new share_qid in RxQ configuration
Xueming Li (6):
ethdev: introduce shared Rx queue app/testpmd: dump device capability and Rx domain info app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 114 +++++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 25 ++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 13 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 ++ doc/guides/rel_notes/release_21_11.rst | 6 + doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 8 + lib/ethdev/rte_ethdev.h | 24 +++ 15 files changed, 379 insertions(+), 6 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v8 1/6 ethdev: introduce shared Rx queue
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Shared Rx queue is identified by share_rxq field of Rx queue configuration. Port A RxQ X can share RxQ with Port B RxQ Y by using same shared Rx queue ID.
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, port_id is identified by mbuf->port. PMD is responsible to resolve shared Rx queue from device and queue data.
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue on one port.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
PMD advertise shared Rx queue capability via RTE_ETH_DEV_CAPA_RXQ_SHARE.
PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
--- doc/guides/nics/features.rst | 13 ++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 +++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 24 +++++++++++++++++++ 6 files changed, 63 insertions(+)
doc/guides/nics/features.rst +13 -0
@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``, ``share_qid``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +11 -0
@@ -123,6 +123,17 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` in + device info is used to indicate the capability. Setting non-zero share + group in Rx queue configuration to enable share, share_qid is used to + identifiy the shared Rx queue in group. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------
doc/guides/rel_notes/release_21_11.rst +6 -0
@@ -75,6 +75,12 @@ New Features operations. * Added multi-process support. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group and share queue ID to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 and
lib/ethdev/rte_ethdev.c +8 -0
@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device.
lib/ethdev/rte_ethdev.h +24 -0
@@ -1044,6 +1044,14 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD is responsible for Rx queue consistency checks to avoid member +* port's configuration contradict to each other. +*/ +uint16_t share_group; +uint16_t share_qid;/**< Shared Rx queue ID in group. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1445,6 +1453,16 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* each queue. Multiple groups is supported by share_group of Rx +* queue configuration. Shared Rx queue is identified by PMD using +* share_qid of Rx queue configuration. Polling any port in the group +* receive packets of all member ports, source port identified by +* mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /*
@@ -1488,6 +1506,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/**
Signature · 1 line
2.33.0
Quoted 8 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and
s/introduce/introduces
Quoted 12 lines
switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Shared Rx queue is identified by
share_rxqfield of Rx queue configuration. Port A RxQ X can share RxQ with Port B RxQ Y by using same shared Rx queue ID.No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports,
port_idis identified bymbuf->port. PMD is responsible to resolve shared Rx queue from device and queue data.
Quoted 6 lines
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue on one port.
More than a device, it should be the PMD which should support it. Right?
Quoted 8 lines
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
Quoted 4 lines
PMD advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
contradict each other.
Quoted 54 lines
Signed-off-by Xueming Li <[email protected]>--- doc/guides/nics/features.rst | 13 ++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 +++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 24 +++++++++++++++++++ 6 files changed, 63 insertions(+)doc/guides/nics/features.rst +13
-0@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``, ``share_qid``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +0
-0@@ -123,6 +123,17 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev)
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 133
Quoted 10 lines
doc/guides/prog_guide/switch_representation.rst +8
-0<https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` in + device info is used to indicate the capability. Setting non-zero share + group in Rx queue configuration to enable share, share_qid is used to + identifiy the shared Rx queue in group. Polling any member port can
s/identifiy/identify
Quoted 62 lines
doc/guides/prog_guide/switch_representation.rst +3
-0+ receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +6
-0@@ -75,6 +75,12 @@ New Features operations. * Added multi-process support. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group and share queue ID to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 andlib/ethdev/rte_ethdev.c +8
-0@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device. lib/ethdev/rte_ethdev.h +8
-0@@ -1044,6 +1044,14 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD is responsible for Rx queue consistency checks to avoid member +* port's configuration contradict to each other. +*/ +uint16_t share_group; +uint16_t share_qid;/**< Shared Rx queue ID in group. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1459
Quoted 7 lines
lib/ethdev/rte_ethdev.h +4
-0@@ -1445,6 +1453,16 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* each queue. Multiple groups is supported by share_group of Rx
are supported by..
Quoted 25 lines
lib/ethdev/rte_ethdev.h +12
-1+* queue configuration. Shared Rx queue is identified by PMD using +* share_qid of Rx queue configuration. Polling any port in the group +* receive packets of all member ports, source port identified by +* mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /* @@ -1488,6 +1506,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/** -- 2.33.0
Quoted 10 lines · Ajit Khaparde
Quoted 8 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and
s/introduce/introduces
Accepted all the comments, thanks!
Quoted 197 lines
Quoted 13 lines
switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Shared Rx queue is identified by
share_rxqfield of Rx queue configuration. Port A RxQ X can share RxQ with Port B RxQ Y by using same shared Rx queue ID.No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports,
port_idis identified bymbuf->port. PMD is responsible to resolve shared Rx queue from device and queue data.Quoted 6 lines
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue on one port.
More than a device, it should be the PMD which should support it. Right?
Quoted 8 lines
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0Quoted 4 lines
PMD advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
contradict each other.
Quoted 54 lines
Signed-off-by Xueming Li <[email protected]>--- doc/guides/nics/features.rst | 13 ++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 +++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 24 +++++++++++++++++++ 6 files changed, 63 insertions(+)doc/guides/nics/features.rst +13
-0@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``, ``share_qid``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsingdoc/guides/nics/features/default.ini +1
-0@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =doc/guides/prog_guide/switch_representation.rst +0
-0@@ -123,6 +123,17 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev)doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 133
Quoted 10 lines
doc/guides/prog_guide/switch_representation.rst +8
-0<https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` in + device info is used to indicate the capability. Setting non-zero share + group in Rx queue configuration to enable share, share_qid is used to + identifiy the shared Rx queue in group. Polling any member port cans/identifiy/identify
Quoted 62 lines
doc/guides/prog_guide/switch_representation.rst +3
-0+ receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +6
-0@@ -75,6 +75,12 @@ New Features operations. * Added multi-process support. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info. + * Added share group and share queue ID to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 andlib/ethdev/rte_ethdev.c +8
-0@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device. lib/ethdev/rte_ethdev.h +8
-0@@ -1044,6 +1044,14 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD is responsible for Rx queue consistency checks to avoid member +* port's configuration contradict to each other. +*/ +uint16_t share_group; +uint16_t share_qid;/**< Shared Rx queue ID in group. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa lib/ethdev/rte_ethdev.h struct rte_eth_conf { · line 1459
Quoted 7 lines
lib/ethdev/rte_ethdev.h +4
-0@@ -1445,6 +1453,16 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* each queue. Multiple groups is supported by share_group of Rx are supported by..
Quoted 25 lines
lib/ethdev/rte_ethdev.h +12
-1+* queue configuration. Shared Rx queue is identified by PMD using +* share_qid of Rx queue configuration. Polling any port in the group +* receive packets of all member ports, source port identified by +* mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /* @@ -1488,6 +1506,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/** -- 2.33.0
Quoted 33 lines · Xueming Li
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduce shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Shared Rx queue is identified by
share_rxqfield of Rx queue configuration. Port A RxQ X can share RxQ with Port B RxQ Y by using same shared Rx queue ID.No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports,
port_idis identified bymbuf->port. PMD is responsible to resolve shared Rx queue from device and queue data.Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported. Device should support mixed configuration by allowing multiple share groups and non-shared Rx queue on one port.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
Quoted 6 lines
PMD advertise shared Rx queue capability via
RTE_ETH_DEV_CAPA_RXQ_SHARE.PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict to each other.
Signed-off-by Xueming Li <[email protected]>
with few nits below:
[snip]
Quoted 6 lines
doc/guides/prog_guide/switch_representation.rst +0
-0@@ -123,6 +123,17 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev)
doc/guides/prog_guide/switch_representation.rst thought as a software "patch panel" front-end for applications. · line 133
Quoted 10 lines
doc/guides/prog_guide/switch_representation.rst +8
-0<https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` in + device info is used to indicate the capability. Setting non-zero share + group in Rx queue configuration to enable share, share_qid is used to + identifiy the shared Rx queue in group. Polling any member port can
identifiy -> identify
Quoted 11 lines
doc/guides/prog_guide/switch_representation.rst +3
-0+ receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------doc/guides/rel_notes/release_21_11.rst +0
-0
doc/guides/rel_notes/release_21_11.rst New Features · line 80
Quoted 6 lines
doc/guides/rel_notes/release_21_11.rst +3
-0@@ -75,6 +75,12 @@ New Features operations. * Added multi-process support. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and rx domain field to switch info.
rx -> Rx
Quoted 6 lines
doc/guides/rel_notes/release_21_11.rst +3
-0+ * Added share group and share queue ID to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 and
[snip]
PATCH v8 2/6 app/testpmd: dump device capability and Rx domain info
In reply to Xueming LiDump device capability and Rx domain ID if shared Rx queue is supported by device.
--- app/test-pmd/config.c | 4 ++++ 1 file changed, 4 insertions(+)
app/test-pmd/config.c +4 -0
@@ -733,6 +733,7 @@ port_infos_display(portid_t port_id)printf ("Max segment number per MTU/TSO: %hu\n" , dev_info.tx_desc_lim.nb_mtu_seg_max); +printf ("Device capabilities: 0x%" PRIx64"\n" , dev_info.dev_capa);/* Show switch info only if valid switch domain and port id is set */ if (dev_info.switch_info.domain_id !=RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ) {
@@ -743,6 +744,9 @@ port_infos_display(portid_t port_id) dev_info.switch_info.domain_id);printf ("Switch Port Id: %u\n" , dev_info.switch_info.port_id); +if ((dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) !=0 ) +printf ("Switch Rx domain: %u\n" , + dev_info.switch_info.rx_domain); } }
Signature · 1 line
2.33.0
PATCH v8 3/6 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share=X" parameter to enable shared RxQ, share if device supports, otherwise fallback to standard RxQ.
Share group number grows per X ports. X defaults to MAX, implies all ports join share group 1. Queue ID is mapped equally with shared Rx queue ID.
Forwarding engine "shared-rxq" should be used which Rx only and update stream statistics correctly.
--- app/test-pmd/config.c | 7 ++++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 20 +++++++++++++++++--- app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 45 insertions(+), 4 deletions(-)
app/test-pmd/config.c +6 -1
@@ -2713,7 +2713,12 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->share_group >0 ) +printf (" share_group=%u share_qid=%u" , + rx_conf->share_group, + rx_conf->share_qid); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +17 -3
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -3393,14 +3398,23 @@ dev_event_callback(const char *device_name, enum rte_dev_event_type type, }static void -rxtx_port_config (struct rte_port *port) +rxtx_port_config (portid_t pid) {uint16_t qid;uint64_t offloads; +struct rte_port *port = &ports[pid];for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE )) { +/* Non-zero share group to enable RxQ share. */ + port->rx_conf[qid].share_group = pid / rxq_share +1 ; + port->rx_conf[qid].share_qid = qid;/* Equal mapping. */ + } +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
@@ -3558,7 +3572,7 @@ init_port_config(void) port->dev_conf.rxmode.mq_mode =ETH_MQ_RX_NONE ; } -rxtx_port_config (port); +rxtx_port_config (pid); ret =eth_macaddr_get_print_err (pid, &port->eth_addr);if (ret !=0 )
@@ -3772,7 +3786,7 @@ init_port_dcb_config(portid_t pid,memcpy (&rte_port->dev_conf, &port_conf,sizeof (struct rte_eth_conf )); -rxtx_port_config (rte_port); +rxtx_port_config (pid);/* VLAN filter */ rte_port->dev_conf.rxmode.offloads |=DEV_RX_OFFLOAD_VLAN_FILTER ;for (i =0 ; i <RTE_DIM (vlan_tags); i++)
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared Rx queue mode if device supports. + Group number grows per X ports. X defaults to MAX, implies all ports + join share group 1. Forwarding engine "shared-rxq" should be used + which Rx only and update stream statistics correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v8 4/6 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v8 5/6 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared Rx queue must be polled on same core. This patch checks and stops forwarding if shared RxQ being scheduled on multiple
cores.
It's suggested to use same number of Rx queues and polling cores.
--- app/test-pmd/config.c | 103 +++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 108 insertions(+), 1 deletion(-)
app/test-pmd/config.c +103 -0
@@ -2890,6 +2890,109 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,lcoreid_t src_lc, +portid_t src_port,queueid_t src_rxq, +uint32_t share_group,queueid_t share_rxq) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* Check remaining cores. */ +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (rxq_conf->share_group != share_group) +continue ; +if (rxq_conf->share_qid != share_rxq) +continue ; +printf ("Shared Rx queue group %u queue %hu can't be scheduled on different cores:\n" , + share_group, share_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf ("Please use --nb-cores=%hu to limit number of forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, lc_id, + fs->rx_port, + fs->rx_queue, + rxq_conf->share_group, + rxq_conf->share_qid)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2236,10 +2236,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v8 6/6 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accordingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
v9 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors in same Rx domain and switch domain could share Rx queue set by specifying non-zero share group value in Rx queue configuration.
All ports that share Rx queue actually shares hardware descriptor queue and feed all Rx queues with one descriptor supply, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group1, 4 shared Rx queues per member port: PF, repr0, repr1 Group2, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
v6:
- replace RxQ offload flag with device offload capability flag
- add Rx domain
- RxQ is shared when share group > 0
- update testpmd accordingly
v7:
- fix testpmd share group id allocation
- change rx_domain to 16bits
v8:
- add new patch for testpmd to show device Rx domain ID and capability
- new share_qid in RxQ configuration
v9:
- fix some spelling
Xueming Li (6):
ethdev: introduce shared Rx queue app/testpmd: dump device capability and Rx domain info app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 114 +++++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 25 ++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 13 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 ++ doc/guides/rel_notes/release_21_11.rst | 6 + doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 8 + lib/ethdev/rte_ethdev.h | 24 +++ 15 files changed, 379 insertions(+), 6 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v9 1/6 ethdev: introduce shared Rx queue
In current DPDK framework, each Rx queue is pre-loaded with mbufs to save incoming packets. For some PMDs, when number of representors scale out in a switch domain, the memory consumption became significant. Polling all ports also leads to high cache miss, high latency and low throughput.
This patch introduces shared Rx queue. Ports in same Rx domain and switch domain could share Rx queue set by specifying non-zero sharing group in Rx queue configuration.
Shared Rx queue is identified by share_rxq field of Rx queue configuration. Port A RxQ X can share RxQ with Port B RxQ Y by using same shared Rx queue ID.
No special API is defined to receive packets from shared Rx queue. Polling any member port of a shared Rx queue receives packets of that queue for all member ports, port_id is identified by mbuf->port. PMD is responsible to resolve shared Rx queue from device and queue data.
Shared Rx queue must be polled in same thread or core, polling a queue ID of any member port is essentially same.
Multiple share groups are supported. PMD should support mixed configuration by allowing multiple share groups and non-shared Rx queue on one port.
Example grouping and polling model to reflect service priority:
Group1, 2 shared Rx queues per port: PF, rep0, rep1 Group2, 1 shared Rx queue per port: rep2, rep3, ... rep127
Core0: poll PF queue0
Core1: poll PF queue1
Core2: poll rep2 queue0
PMD advertise shared Rx queue capability via RTE_ETH_DEV_CAPA_RXQ_SHARE.
PMD is responsible for shared Rx queue consistency checks to avoid member port's configuration contradict each other.
--- doc/guides/nics/features.rst | 13 ++++++++++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 +++++++++ doc/guides/rel_notes/release_21_11.rst | 6 +++++ lib/ethdev/rte_ethdev.c | 8 +++++++ lib/ethdev/rte_ethdev.h | 24 +++++++++++++++++++ 6 files changed, 63 insertions(+)
doc/guides/nics/features.rst +13 -0
@@ -615,6 +615,19 @@ Supports inner packet L4 checksum. ``tx_offload_capa,tx_queue_offload_capa:DEV_TX_OFFLOAD_OUTER_UDP_CKSUM``. +.. _nic_features_shared_rx_queue: + +Shared Rx queue +--------------- + +Supports shared Rx queue for ports in same Rx domain of a switch domain. + +* **[uses] rte_eth_dev_info**: ``dev_capa:RTE_ETH_DEV_CAPA_RXQ_SHARE``. +* **[uses] rte_eth_dev_info,rte_eth_switch_info**: ``rx_domain``, ``domain_id``. +* **[uses] rte_eth_rxconf**: ``share_group``, ``share_qid``. +* **[provides] mbuf**: ``mbuf.port``. + + .. _nic_features_packet_type_parsing: Packet type parsing
doc/guides/nics/features/default.ini +1 -0
@@ -19,6 +19,7 @@ Free Tx mbuf on demand = Queue start/stop = Runtime Rx queue setup = Runtime Tx queue setup = +Shared Rx queue = Burst mode info = Power mgmt address monitor = MTU update =
doc/guides/prog_guide/switch_representation.rst +11 -0
@@ -123,6 +123,17 @@ thought as a software "patch panel" front-end for applications. .. [1] `Ethernet switch device driver model (switchdev) <https://www.kernel.org/doc/Documentation/networking/switchdev.txt>`_ +- For some PMDs, memory usage of representors is huge when number of + representor grows, mbufs are allocated for each descriptor of Rx queue. + Polling large number of ports brings more CPU load, cache miss and + latency. Shared Rx queue can be used to share Rx queue between PF and + representors among same Rx domain. ``RTE_ETH_DEV_CAPA_RXQ_SHARE`` in + device info is used to indicate the capability. Setting non-zero share + group in Rx queue configuration to enable share, share_qid is used to + identify the shared Rx queue in group. Polling any member port can + receive packets of all member ports in the group, port ID is saved in + ``mbuf.port``. + Basic SR-IOV ------------
doc/guides/rel_notes/release_21_11.rst +6 -0
@@ -75,6 +75,12 @@ New Features operations. * Added multi-process support. +* **Added ethdev shared Rx queue support.** + + * Added new device capability flag and Rx domain field to switch info. + * Added share group and share queue ID to Rx queue configuration. + * Added testpmd support and dedicate forwarding engine. + * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4 and
lib/ethdev/rte_ethdev.c +8 -0
@@ -2159,6 +2159,14 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,return -EINVAL ; } +if (local_conf.share_group >0 && + (dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) ==0 ) { +RTE_ETHDEV_LOG (ERR , +"Ethdev port_id=%d rx_queue_id=%d, enabled share_group=%hu while device doesn't support Rx queue share\n" , + port_id, rx_queue_id, local_conf.share_group); +return -EINVAL ; + } +/* * If LRO is enabled, check that the maximum aggregated packet * size is supported by the configured device.
lib/ethdev/rte_ethdev.h +24 -0
@@ -1044,6 +1044,14 @@ struct rte_eth_rxconf {uint8_t rx_drop_en;/**< Drop packets if no descriptors are available. */ uint8_t rx_deferred_start;/**< Do not start queue with rte_eth_dev_start(). */ uint16_t rx_nseg;/**< Number of descriptions in rx_seg array. */ +/** +* Share group index in Rx domain and switch domain. +* Non-zero value to enable Rx queue share, zero value disable share. +* PMD is responsible for Rx queue consistency checks to avoid member +* port's configuration contradict to each other. +*/ +uint16_t share_group; +uint16_t share_qid;/**< Shared Rx queue ID in group. */ /** * Per-queue Rx offloads to be set using DEV_RX_OFFLOAD_* flags. * Only offloads set on rx_queue_offload_capa or rx_offload_capa
@@ -1445,6 +1453,16 @@ struct rte_eth_conf {#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001/** Device supports Tx queue setup after device started. */ #define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002 +/** +* Device supports shared Rx queue among ports within Rx domain and +* switch domain. Mbufs are consumed by shared Rx queue instead of +* each queue. Multiple groups are supported by share_group of Rx +* queue configuration. Shared Rx queue is identified by PMD using +* share_qid of Rx queue configuration. Polling any port in the group +* receive packets of all member ports, source port identified by +* mbuf->port field. +*/ +#define RTE_ETH_DEV_CAPA_RXQ_SHARE RTE_BIT64(2)/**@}*/ /*
@@ -1488,6 +1506,12 @@ struct rte_eth_switch_info {* but each driver should explicitly define the mapping of switch * port identifier to that physical interconnect/switch */ +/** +* Shared Rx queue sub-domain boundary. Only ports in same Rx domain +* and switch domain can share Rx queue. Valid only if device advertised +* RTE_ETH_DEV_CAPA_RXQ_SHARE capability. +*/ +uint16_t rx_domain; };/**
Signature · 1 line
2.33.0
PATCH v9 2/6 app/testpmd: dump device capability and Rx domain info
In reply to Xueming LiDump device capability and Rx domain ID if shared Rx queue is supported by device.
--- app/test-pmd/config.c | 4 ++++ 1 file changed, 4 insertions(+)
app/test-pmd/config.c +4 -0
@@ -733,6 +733,7 @@ port_infos_display(portid_t port_id)printf ("Max segment number per MTU/TSO: %hu\n" , dev_info.tx_desc_lim.nb_mtu_seg_max); +printf ("Device capabilities: 0x%" PRIx64"\n" , dev_info.dev_capa);/* Show switch info only if valid switch domain and port id is set */ if (dev_info.switch_info.domain_id !=RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ) {
@@ -743,6 +744,9 @@ port_infos_display(portid_t port_id) dev_info.switch_info.domain_id);printf ("Switch Port Id: %u\n" , dev_info.switch_info.port_id); +if ((dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) !=0 ) +printf ("Switch Rx domain: %u\n" , + dev_info.switch_info.rx_domain); } }
Signature · 1 line
2.33.0
Re: [dpdk-dev] [PATCH v9 2/6] app/testpmd: dump device capability and Rx domain info
Quoted 4 lines · Xueming Li
Dump device capability and Rx domain ID if shared Rx queue is supported by device.
Signed-off-by Xueming Li <[email protected]>
LGTM except one minor note:
app/test-pmd/config.c port_infos_display(portid_t port_id) · line 736
Quoted 13 lines
--- app/test-pmd/config.c | 4 ++++ 1 file changed, 4 insertions(+)app/test-pmd/config.c +1
-0@@ -733,6 +733,7 @@ port_infos_display(portid_t port_id)printf ("Max segment number per MTU/TSO: %hu\n" , dev_info.tx_desc_lim.nb_mtu_seg_max); +printf ("Device capabilities: 0x%" PRIx64"\n" , dev_info.dev_capa);
IMHO, it should be decoded
Quoted 14 lines
app/test-pmd/config.c +3
-0/* Show switch info only if valid switch domain and port id is set */ if (dev_info.switch_info.domain_id !=RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ) {@@ -743,6 +744,9 @@ port_infos_display(portid_t port_id) dev_info.switch_info.domain_id);printf ("Switch Port Id: %u\n" , dev_info.switch_info.port_id); +if ((dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) !=0 ) +printf ("Switch Rx domain: %u\n" , + dev_info.switch_info.rx_domain); } }
Re: [dpdk-dev] [PATCH v9 2/6] app/testpmd: dump device capability and Rx domain info
Quoted 22 lines · Andrew Rybchenko
Quoted 4 lines · Xueming Li
Dump device capability and Rx domain ID if shared Rx queue is supported by device.
Signed-off-by Xueming Li <[email protected]>LGTM except one minor note:
Acked-by Andrew Rybchenko <[email protected]>Quoted 12 lines
--- app/test-pmd/config.c | 4 ++++ 1 file changed, 4 insertions(+)app/test-pmd/config.c +0
-0@@ -733,6 +733,7 @@ port_infos_display(portid_t port_id)printf ("Max segment number per MTU/TSO: %hu\n" , dev_info.tx_desc_lim.nb_mtu_seg_max);
Quoted 3 lines
app/test-pmd/config.c port_infos_display(portid_t port_id) · line 736
Quoted 1 line
app/test-pmd/config.c +1
-0+printf ("Device capabilities: 0x%" PRIx64"\n" , dev_info.dev_capa);IMHO, it should be decoded
Thanks for checking this, do you mean decode to readable names? Then we need a new API rte_eth_dev_capability_name(), it's simple, but is it ok to add API w/o RFC?
Quoted 16 lines
Quoted 15 lines
app/test-pmd/config.c +3
-0/* Show switch info only if valid switch domain and port id is set */ if (dev_info.switch_info.domain_id !=RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ) {@@ -743,6 +744,9 @@ port_infos_display(portid_t port_id) dev_info.switch_info.domain_id);printf ("Switch Port Id: %u\n" , dev_info.switch_info.port_id); +if ((dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) !=0 ) +printf ("Switch Rx domain: %u\n" , + dev_info.switch_info.rx_domain); } }
Re: [dpdk-dev] [PATCH v9 2/6] app/testpmd: dump device capability and Rx domain info
Quoted 23 lines · Xueming(Steven) Li
Quoted 22 lines · Andrew Rybchenko
Quoted 4 lines · Xueming Li
Dump device capability and Rx domain ID if shared Rx queue is supported by device.
Signed-off-by Xueming Li <[email protected]>LGTM except one minor note:
Acked-by Andrew Rybchenko <[email protected]>Quoted 12 lines
--- app/test-pmd/config.c | 4 ++++ 1 file changed, 4 insertions(+)app/test-pmd/config.c +0
-0@@ -733,6 +733,7 @@ port_infos_display(portid_t port_id)printf ("Max segment number per MTU/TSO: %hu\n" , dev_info.tx_desc_lim.nb_mtu_seg_max);
Quoted 7 lines
Quoted 3 lines
app/test-pmd/config.c port_infos_display(portid_t port_id) · line 736
Quoted 1 line
app/test-pmd/config.c +1
-0+printf ("Device capabilities: 0x%" PRIx64"\n" , dev_info.dev_capa);IMHO, it should be decoded
Thanks for checking this, do you mean decode to readable names? Then we need a new API
rte_eth_dev_capability_name(), it's simple, but is it ok to add API w/o RFC?
It is trivial. So, I think it should be OK.
PATCH v9 3/6 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share=X" parameter to enable shared RxQ, share if device supports, otherwise fallback to standard RxQ.
Share group number grows per X ports. X defaults to MAX, implies all ports join share group 1. Queue ID is mapped equally with shared Rx queue ID.
Forwarding engine "shared-rxq" should be used which Rx only and update stream statistics correctly.
--- app/test-pmd/config.c | 7 ++++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 20 +++++++++++++++++--- app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 45 insertions(+), 4 deletions(-)
app/test-pmd/config.c +6 -1
@@ -2713,7 +2713,12 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->share_group >0 ) +printf (" share_group=%u share_qid=%u" , + rx_conf->share_group, + rx_conf->share_qid); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +17 -3
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -3393,14 +3398,23 @@ dev_event_callback(const char *device_name, enum rte_dev_event_type type, }static void -rxtx_port_config (struct rte_port *port) +rxtx_port_config (portid_t pid) {uint16_t qid;uint64_t offloads; +struct rte_port *port = &ports[pid];for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE )) { +/* Non-zero share group to enable RxQ share. */ + port->rx_conf[qid].share_group = pid / rxq_share +1 ; + port->rx_conf[qid].share_qid = qid;/* Equal mapping. */ + } +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
@@ -3558,7 +3572,7 @@ init_port_config(void) port->dev_conf.rxmode.mq_mode =ETH_MQ_RX_NONE ; } -rxtx_port_config (port); +rxtx_port_config (pid); ret =eth_macaddr_get_print_err (pid, &port->eth_addr);if (ret !=0 )
@@ -3772,7 +3786,7 @@ init_port_dcb_config(portid_t pid,memcpy (&rte_port->dev_conf, &port_conf,sizeof (struct rte_eth_conf )); -rxtx_port_config (rte_port); +rxtx_port_config (pid);/* VLAN filter */ rte_port->dev_conf.rxmode.offloads |=DEV_RX_OFFLOAD_VLAN_FILTER ;for (i =0 ; i <RTE_DIM (vlan_tags); i++)
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared Rx queue mode if device supports. + Group number grows per X ports. X defaults to MAX, implies all ports + join share group 1. Forwarding engine "shared-rxq" should be used + which Rx only and update stream statistics correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v9 4/6 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v9 5/6 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared Rx queue must be polled on same core. This patch checks and stops forwarding if shared RxQ being scheduled on multiple
cores.
It's suggested to use same number of Rx queues and polling cores.
--- app/test-pmd/config.c | 103 +++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 108 insertions(+), 1 deletion(-)
app/test-pmd/config.c +103 -0
@@ -2890,6 +2890,109 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,lcoreid_t src_lc, +portid_t src_port,queueid_t src_rxq, +uint32_t share_group,queueid_t share_rxq) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* Check remaining cores. */ +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (rxq_conf->share_group != share_group) +continue ; +if (rxq_conf->share_qid != share_rxq) +continue ; +printf ("Shared Rx queue group %u queue %hu can't be scheduled on different cores:\n" , + share_group, share_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf ("Please use --nb-cores=%hu to limit number of forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, lc_id, + fs->rx_port, + fs->rx_queue, + rxq_conf->share_group, + rxq_conf->share_qid)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2236,10 +2236,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v9 6/6 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accordingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
v10 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors in same Rx domain and switch domain could share Rx queue set by specifying non-zero share group value in Rx queue configuration.
All ports that share Rx queue actually shares hardware descriptor queue and feed all Rx queues with one descriptor supply, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group1, 4 shared Rx queues per member port: PF, repr0, repr1 Group2, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
v6:
- replace RxQ offload flag with device offload capability flag
- add Rx domain
- RxQ is shared when share group > 0
- update testpmd accordingly
v7:
- fix testpmd share group id allocation
- change rx_domain to 16bits
v8:
- add new patch for testpmd to show device Rx domain ID and capability
- new share_qid in RxQ configuration
v9:
- fix some spelling
v10:
- add device capability name api
Xueming Li (6):
ethdev: new API to resolve device capability name app/testpmd: dump device capability and Rx domain info app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 139 +++++++++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 25 +++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/testpmd_app_ug/run_app.rst | 8 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 30 ++++ lib/ethdev/rte_ethdev.h | 14 ++ lib/ethdev/version.map | 3 + 12 files changed, 388 insertions(+), 6 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0
PATCH v10 1/6 ethdev: new API to resolve device capability name
This patch adds API to return name of device capability.
--- lib/ethdev/rte_ethdev.c | 30 ++++++++++++++++++++++++++++++ lib/ethdev/rte_ethdev.h | 14 ++++++++++++++ lib/ethdev/version.map | 3 +++ 3 files changed, 47 insertions(+)
lib/ethdev/rte_ethdev.c +30 -0
@@ -165,6 +165,20 @@ static const struct {#undef RTE_TX_OFFLOAD_BIT2STR +#define RTE_ETH_DEV_CAPA_BIT2STR (_name) \ + { RTE_ETH_DEV_CAPA_##_name, #_name } + +static const struct { +uint64_t offload; +const char *name; +} rte_eth_dev_capa_names[] = { +RTE_ETH_DEV_CAPA_BIT2STR (RUNTIME_RX_QUEUE_SETUP ), +RTE_ETH_DEV_CAPA_BIT2STR (RUNTIME_TX_QUEUE_SETUP ), +RTE_ETH_DEV_CAPA_BIT2STR (RXQ_SHARE ), +}; + +#undef RTE_ETH_DEV_CAPA_BIT2STR +/** * The user application callback description. *
@@ -1260,6 +1274,22 @@ rte_eth_dev_tx_offload_name(uint64_t offload)return name; } +const char * +rte_eth_dev_capability_name (uint64_t capability) +{ +const char *name ="UNKNOWN" ; +unsigned int i; + +for (i =0 ; i <RTE_DIM (rte_eth_dev_capa_names); ++i) { +if (capability == rte_eth_dev_capa_names[i].offload) { + name = rte_eth_dev_capa_names[i].name; +break ; + } + } + +return name; +} +static inline int eth_dev_check_lro_pkt_size (uint16_t port_id,uint32_t config_size,uint32_t max_rx_pkt_len,uint32_t dev_info_size)
lib/ethdev/rte_ethdev.h +14 -0
@@ -2109,6 +2109,20 @@ const char *rte_eth_dev_rx_offload_name(uint64_t offload);*/ const char *rte_eth_dev_tx_offload_name (uint64_t offload); +/** +* @warning +* @b EXPERIMENTAL: this API may change without prior notice. +* +* Get RTE_ETH_DEV_CAPA_* flag name. +* +* @param capability +* Capability flag. +* @return +* Capability name or 'UNKNOWN' if the flag cannot be recognized. +*/ +__rte_experimental +const char *rte_eth_dev_capability_name(uint64_t capability); +/** * Configure an Ethernet device. * This function must be invoked first before any other function in the
lib/ethdev/version.map +3 -0
@@ -245,6 +245,9 @@ EXPERIMENTAL { rte_mtr_meter_policy_delete; rte_mtr_meter_policy_update; rte_mtr_meter_policy_validate; + + # added in 21.11 + rte_eth_dev_capability_name; }; INTERNAL {
Signature · 1 line
2.33.0
PATCH v10 2/6 app/testpmd: dump device capability and Rx domain info
In reply to Xueming LiDump device capability and Rx domain ID if shared Rx queue is supported by device.
--- app/test-pmd/config.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
app/test-pmd/config.c +29 -0
@@ -582,6 +582,29 @@ device_infos_display(const char *identifier)rte_devargs_reset (&da); } +static void +print_dev_capabilities (uint64_t capabilities) +{ +uint64_t single_capa; +int begin; +int end; +int bit; + +if (capabilities ==0 ) +return ; + + begin =__builtin_ctzll (capabilities); + end =sizeof (capabilities) *CHAR_BIT -__builtin_clzll (capabilities); + + single_capa =1ULL << begin; +for (bit = begin; bit < end; bit++) { +if (capabilities & single_capa) +printf (" %s" , +rte_eth_dev_capability_name (single_capa)); + single_capa <<=1 ; + } +} +void port_infos_display (portid_t port_id) {
@@ -733,6 +756,9 @@ port_infos_display(portid_t port_id)printf ("Max segment number per MTU/TSO: %hu\n" , dev_info.tx_desc_lim.nb_mtu_seg_max); +printf ("Device capabilities: 0x%" PRIx64"(" , dev_info.dev_capa); +print_dev_capabilities (dev_info.dev_capa); +printf (" )\n" );/* Show switch info only if valid switch domain and port id is set */ if (dev_info.switch_info.domain_id !=RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID ) {
@@ -743,6 +769,9 @@ port_infos_display(portid_t port_id) dev_info.switch_info.domain_id);printf ("Switch Port Id: %u\n" , dev_info.switch_info.port_id); +if ((dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) !=0 ) +printf ("Switch Rx domain: %u\n" , + dev_info.switch_info.rx_domain); } }
Signature · 1 line
2.33.0
PATCH v10 3/6 app/testpmd: new parameter to enable shared Rx queue
In reply to Xueming LiAdds "--rxq-share=X" parameter to enable shared RxQ, share if device supports, otherwise fallback to standard RxQ.
Share group number grows per X ports. X defaults to MAX, implies all ports join share group 1. Queue ID is mapped equally with shared Rx queue ID.
Forwarding engine "shared-rxq" should be used which Rx only and update stream statistics correctly.
--- app/test-pmd/config.c | 7 ++++++- app/test-pmd/parameters.c | 13 +++++++++++++ app/test-pmd/testpmd.c | 20 +++++++++++++++++--- app/test-pmd/testpmd.h | 2 ++ doc/guides/testpmd_app_ug/run_app.rst | 7 +++++++ 5 files changed, 45 insertions(+), 4 deletions(-)
app/test-pmd/config.c +6 -1
@@ -2738,7 +2738,12 @@ rxtx_config_display(void)printf (" RX threshold registers: pthresh=%d hthresh=%d " " wthresh=%d\n" , pthresh_tmp, hthresh_tmp, wthresh_tmp); -printf (" RX Offloads=0x%" PRIx64"\n" , offloads_tmp); +printf (" RX Offloads=0x%" PRIx64, offloads_tmp); +if (rx_conf->share_group >0 ) +printf (" share_group=%u share_qid=%u" , + rx_conf->share_group, + rx_conf->share_qid); +printf ("\n" ); }/* per tx queue config only for first queue to be less verbose */
app/test-pmd/parameters.c +13 -0
@@ -167,6 +167,7 @@ usage(char* progname)printf (" --tx-ip=src,dst: IP addresses in Tx-only mode\n" );printf (" --tx-udp=src[,dst]: UDP ports in Tx-only mode\n" );printf (" --eth-link-speed: force link speed.\n" ); +printf (" --rxq-share: number of ports per shared rxq groups, defaults to MAX(1 group)\n" );printf (" --disable-link-check: disable check on link status when " "starting/stopping ports.\n" );printf (" --disable-device-start: do not automatically start port\n" );
@@ -607,6 +608,7 @@ launch_args_parse(int argc, char** argv) { "rxpkts", 1, 0, 0 }, { "txpkts", 1, 0, 0 }, { "txonly-multi-flow", 0, 0, 0 }, + { "rxq-share", 2, 0, 0 }, { "eth-link-speed", 1, 0, 0 }, { "disable-link-check", 0, 0, 0 }, { "disable-device-start", 0, 0, 0 },
@@ -1271,6 +1273,17 @@ launch_args_parse(int argc, char** argv) }if (!strcmp (lgopts[opt_idx].name,"txonly-multi-flow" )) txonly_multi_flow =1 ; +if (!strcmp (lgopts[opt_idx].name,"rxq-share" )) { +if (optarg ==NULL ) { + rxq_share =UINT32_MAX ; + }else { + n =atoi (optarg); +if (n >=0 ) + rxq_share = (uint32_t )n; +else +rte_exit (EXIT_FAILURE ,"rxq-share must be >= 0\n" ); + } + }if (!strcmp (lgopts[opt_idx].name,"no-flush-rx" )) no_flush_rx =1 ;if (!strcmp (lgopts[opt_idx].name,"eth-link-speed" )) {
app/test-pmd/testpmd.c +17 -3
@@ -498,6 +498,11 @@ uint8_t record_core_cycles;*/ uint8_t record_burst_stats; +/* +* Number of ports per shared Rx queue group, 0 disable. +*/ +uint32_t rxq_share; +unsigned int num_sockets =0 ;unsigned int socket_ids[RTE_MAX_NUMA_NODES ];
@@ -3393,14 +3398,23 @@ dev_event_callback(const char *device_name, enum rte_dev_event_type type, }static void -rxtx_port_config (struct rte_port *port) +rxtx_port_config (portid_t pid) {uint16_t qid;uint64_t offloads; +struct rte_port *port = &ports[pid];for (qid =0 ; qid < nb_rxq; qid++) { offloads = port->rx_conf[qid].offloads; port->rx_conf[qid] = port->dev_info.default_rxconf; + +if (rxq_share >0 && + (port->dev_info.dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE )) { +/* Non-zero share group to enable RxQ share. */ + port->rx_conf[qid].share_group = pid / rxq_share +1 ; + port->rx_conf[qid].share_qid = qid;/* Equal mapping. */ + } +if (offloads !=0 ) port->rx_conf[qid].offloads = offloads;
@@ -3558,7 +3572,7 @@ init_port_config(void) port->dev_conf.rxmode.mq_mode =ETH_MQ_RX_NONE ; } -rxtx_port_config (port); +rxtx_port_config (pid); ret =eth_macaddr_get_print_err (pid, &port->eth_addr);if (ret !=0 )
@@ -3772,7 +3786,7 @@ init_port_dcb_config(portid_t pid,memcpy (&rte_port->dev_conf, &port_conf,sizeof (struct rte_eth_conf )); -rxtx_port_config (rte_port); +rxtx_port_config (pid);/* VLAN filter */ rte_port->dev_conf.rxmode.offloads |=DEV_RX_OFFLOAD_VLAN_FILTER ;for (i =0 ; i <RTE_DIM (vlan_tags); i++)
app/test-pmd/testpmd.h +2 -0
@@ -477,6 +477,8 @@ extern enum tx_pkt_split tx_pkt_split;extern uint8_t txonly_multi_flow; +extern uint32_t rxq_share; +extern uint16_t nb_pkt_per_burst;extern uint16_t nb_pkt_flowgen_clones;extern int nb_flows_flowgen;
doc/guides/testpmd_app_ug/run_app.rst +7 -0
@@ -389,6 +389,13 @@ The command line options are: Generate multiple flows in txonly mode. +* ``--rxq-share=[X]`` + + Create queues in shared Rx queue mode if device supports. + Group number grows per X ports. X defaults to MAX, implies all ports + join share group 1. Forwarding engine "shared-rxq" should be used + which Rx only and update stream statistics correctly. + * ``--eth-link-speed`` Set a forced link speed to the ethernet port::
Signature · 1 line
2.33.0
PATCH v10 4/6 app/testpmd: dump port info for shared Rx queue
In reply to Xueming LiIn case of shared Rx queue, polling any member port returns mbufs for all members. This patch dumps mbuf->port for each packet.
--- app/test-pmd/util.c | 3 +++ 1 file changed, 3 insertions(+)
app/test-pmd/util.c +3 -0
@@ -100,6 +100,9 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],struct rte_flow_restore_info info = {0 , }; mb = pkts[i]; +if (rxq_share >0 ) +MKDUMPSTR (print_buf, buf_size, cur_len,"port %u, " , + mb->port); eth_hdr =rte_pktmbuf_read (mb,0 ,sizeof (_eth_hdr), &_eth_hdr); eth_type =RTE_BE_TO_CPU_16 (eth_hdr->ether_type); packet_type = mb->packet_type;
Signature · 1 line
2.33.0
PATCH v10 5/6 app/testpmd: force shared Rx queue polled on same core
In reply to Xueming LiShared Rx queue must be polled on same core. This patch checks and stops forwarding if shared RxQ being scheduled on multiple
cores.
It's suggested to use same number of Rx queues and polling cores.
--- app/test-pmd/config.c | 103 +++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.c | 4 +- app/test-pmd/testpmd.h | 2 + 3 files changed, 108 insertions(+), 1 deletion(-)
app/test-pmd/config.c +103 -0
@@ -2915,6 +2915,109 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key, } } +/* +* Check whether a shared rxq scheduled on other lcores. +*/ +static bool +fwd_stream_on_other_lcores (uint16_t domain_id,lcoreid_t src_lc, +portid_t src_port,queueid_t src_rxq, +uint32_t share_group,queueid_t share_rxq) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* Check remaining cores. */ +for (lc_id = src_lc +1 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +if (domain_id != port->dev_info.switch_info.domain_id) +continue ; +if (rxq_conf->share_group != share_group) +continue ; +if (rxq_conf->share_qid != share_rxq) +continue ; +printf ("Shared Rx queue group %u queue %hu can't be scheduled on different cores:\n" , + share_group, share_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + src_lc, src_port, src_rxq); +printf (" lcore %hhu Port %hu queue %hu\n" , + lc_id, fs->rx_port, fs->rx_queue); +printf ("Please use --nb-cores=%hu to limit number of forwarding cores\n" , + nb_rxq); +return true; + } + } +return false; +} + +/* +* Check shared rxq configuration. +* +* Shared group must not being scheduled on different core. +*/ +bool +pkt_fwd_shared_rxq_check (void ) +{ +streamid_t sm_id; +streamid_t nb_fs_per_lcore; +lcoreid_t nb_fc; +lcoreid_t lc_id; +struct fwd_stream *fs; +uint16_t domain_id; +struct rte_port *port; +struct rte_eth_dev_info *dev_info; +struct rte_eth_rxconf *rxq_conf; + + nb_fc = cur_fwd_config.nb_fwd_lcores; +/* +* Check streams on each core, make sure the same switch domain + +* group + queue doesn't get scheduled on other cores. +*/ +for (lc_id =0 ; lc_id < nb_fc; lc_id++) { + sm_id = fwd_lcores[lc_id]->stream_idx; + nb_fs_per_lcore = fwd_lcores[lc_id]->stream_nb; +for (; sm_id < fwd_lcores[lc_id]->stream_idx + nb_fs_per_lcore; + sm_id++) { + fs = fwd_streams[sm_id]; +/* Update lcore info stream being scheduled. */ + fs->lcore = fwd_lcores[lc_id]; + port = &ports[fs->rx_port]; + dev_info = &port->dev_info; + rxq_conf = &port->rx_conf[fs->rx_queue]; +if ((dev_info->dev_capa &RTE_ETH_DEV_CAPA_RXQ_SHARE ) + ==0 ) +/* Not shared rxq. */ +continue ; +/* Check shared rxq not scheduled on remaining cores. */ + domain_id = port->dev_info.switch_info.domain_id; +if (fwd_stream_on_other_lcores (domain_id, lc_id, + fs->rx_port, + fs->rx_queue, + rxq_conf->share_group, + rxq_conf->share_qid)) +return false; + } + } +return true; +} +/* * Setup forwarding configuration for each logical core. */
app/test-pmd/testpmd.c +3 -1
@@ -2236,10 +2236,12 @@ start_packet_forwarding(int with_tx_first)fwd_config_setup (); +pkt_fwd_config_display (&cur_fwd_config); +if (!pkt_fwd_shared_rxq_check ()) +return ;if (!no_flush_rx)flush_fwd_rx_queues (); -pkt_fwd_config_display (&cur_fwd_config);rxtx_config_display ();fwd_stats_reset ();
app/test-pmd/testpmd.h +2 -0
@@ -144,6 +144,7 @@ struct fwd_stream {uint64_t core_cycles;/**< used for RX and TX processing */ struct pkt_burst_stats rx_burst_stats;struct pkt_burst_stats tx_burst_stats; +struct fwd_lcore *lcore;/**< Lcore being scheduled. */ };/**
@@ -795,6 +796,7 @@ void port_summary_header_display(void);void rx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void tx_queue_infos_display (portid_t port_idi,uint16_t queue_id);void fwd_lcores_config_display (void ); +bool pkt_fwd_shared_rxq_check (void );void pkt_fwd_config_display (struct fwd_config *cfg);void rxtx_config_display (void );void fwd_config_setup (void );
Signature · 1 line
2.33.0
PATCH v10 6/6 app/testpmd: add forwarding engine for shared Rx queue
In reply to Xueming LiTo support shared Rx queue, this patch introduces dedicate forwarding engine. The engine groups received packets by mbuf->port into sub-group, updates stream statistics and simply frees packets.
--- app/test-pmd/meson.build | 1 + app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++++ app/test-pmd/testpmd.c | 1 + app/test-pmd/testpmd.h | 1 + doc/guides/testpmd_app_ug/run_app.rst | 1 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- 6 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
app/test-pmd/meson.build +1 -0
@@ -21,6 +21,7 @@ sources = files( 'noisy_vnf.c', 'parameters.c', 'rxonly.c', + 'shared_rxq_fwd.c', 'testpmd.c', 'txonly.c', 'util.c',
app/test-pmd/shared_rxq_fwd.c new file +148 -0
148 lines not on this page · raw message
app/test-pmd/testpmd.c +1 -0
@@ -188,6 +188,7 @@ struct fwd_engine * fwd_engines[] = {#ifdef RTE_LIBRTE_IEEE1588 &ieee1588_fwd_engine, #endif + &shared_rxq_engine, NULL, };
app/test-pmd/testpmd.h +1 -0
@@ -299,6 +299,7 @@ extern struct fwd_engine five_tuple_swap_fwd_engine;#ifdef RTE_LIBRTE_IEEE1588 extern struct fwd_engine ieee1588_fwd_engine;#endif +extern struct fwd_engine shared_rxq_engine;extern struct fwd_engine * fwd_engines[];/**< NULL terminated array. */ extern cmdline_parse_inst_t cmd_set_raw;
doc/guides/testpmd_app_ug/run_app.rst +1 -0
@@ -252,6 +252,7 @@ The command line options are: tm noisy 5tswap + shared-rxq * ``--rss-ip``
doc/guides/testpmd_app_ug/testpmd_funcs.rst +4 -1
@@ -314,7 +314,7 @@ set fwd Set the packet forwarding mode:: testpmd> set fwd (io|mac|macswap|flowgen| \ - rxonly|txonly|csum|icmpecho|noisy|5tswap) (""|retry) + rxonly|txonly|csum|icmpecho|noisy|5tswap|shared-rxq) (""|retry) ``retry`` can be specified for forwarding engines except ``rx_only``.
@@ -357,6 +357,9 @@ The available information categories are: L4 swaps the source port and destination port of transport layer (TCP and UDP). +* ``shared-rxq``: Receive only for shared Rx queue. + Resolve packet source port from mbuf and update stream statistics accordingly. + Example:: testpmd> set fwd rxonly
Signature · 1 line
2.33.0
v10 cover ethdev: introduce shared Rx queue
In reply to Xueming LiIn current DPDK framework, all Rx queues is pre-loaded with mbufs for incoming packets. When number of representors scale out in a switch domain, the memory consumption became significant. Further more, polling all ports leads to high cache miss, high latency and low throughputs.
This patch introduces shared Rx queue. PF and representors in same Rx domain and switch domain could share Rx queue set by specifying non-zero share group value in Rx queue configuration.
All ports that share Rx queue actually shares hardware descriptor queue and feed all Rx queues with one descriptor supply, memory is saved.
Polling any queue using same shared Rx queue receives packets from all member ports. Source port is identified by mbuf->port.
Multiple groups is supported by group ID. Port queue number in a shared group should be identical. Queue index is 1:1 mapped in shared group. An example of two share groups:
Group1, 4 shared Rx queues per member port: PF, repr0, repr1 Group2, 2 shared Rx queues per member port: repr2, repr3, ... repr127 Poll first port for each group:
core port queue
0 0 0
1 0 1
2 0 2
3 0 3
4 2 0
5 2 1
Shared Rx queue must be polled on single thread or core. If both PF0 and representor0 joined same share group, can't poll pf0rxq0 on core1 and rep0rxq0 on core2. Actually, polling one port within share group is sufficient since polling any port in group will return packets for any port in group.
There was some discussion to aggregate member ports in same group into a dummy port, several ways to achieve it. Since it optional, need to collect more feedback and requirement from user, make better decision later.
v1:
- initial version
v2:
- add testpmd patches
v3:
- change common forwarding api to macro for performance, thanks Jerin.
- save global variable accessed in forwarding to flowstream to minimize cache miss
- combined patches for each forwarding engine
- support multiple groups in testpmd "--share-rxq" parameter
- new api to aggregate shared rxq group
v4:
- spelling fixes
- remove shared-rxq support for all forwarding engines
- add dedicate shared-rxq forwarding engine
v5:
- fix grammars
- remove aggregate api and leave it for later discussion
- add release notes
- add deployment example
v6:
- replace RxQ offload flag with device offload capability flag
- add Rx domain
- RxQ is shared when share group > 0
- update testpmd accordingly
v7:
- fix testpmd share group id allocation
- change rx_domain to 16bits
v8:
- add new patch for testpmd to show device Rx domain ID and capability
- new share_qid in RxQ configuration
v9:
- fix some spelling
v10:
- add device capability name api
Xueming Li (7):
ethdev: introduce shared Rx queue
ethdev: new API to resolve device capability name app/testpmd: dump device capability and Rx domain info app/testpmd: new parameter to enable shared Rx queue app/testpmd: dump port info for shared Rx queue app/testpmd: force shared Rx queue polled on same core app/testpmd: add forwarding engine for shared Rx queue
app/test-pmd/config.c | 139 +++++++++++++++- app/test-pmd/meson.build | 1 + app/test-pmd/parameters.c | 13 ++ app/test-pmd/shared_rxq_fwd.c | 148 ++++++++++++++++++ app/test-pmd/testpmd.c | 25 ++- app/test-pmd/testpmd.h | 5 + app/test-pmd/util.c | 3 + doc/guides/nics/features.rst | 13 ++ doc/guides/nics/features/default.ini | 1 + .../prog_guide/switch_representation.rst | 11 ++ doc/guides/rel_notes/release_21_11.rst | 6 + doc/guides/testpmd_app_ug/run_app.rst | 8 + doc/guides/testpmd_app_ug/testpmd_funcs.rst | 5 +- lib/ethdev/rte_ethdev.c | 38 +++++ lib/ethdev/rte_ethdev.h | 38 +++++ lib/ethdev/version.map | 3 + 16 files changed, 451 insertions(+), 6 deletions(-) create mode 100644 app/test-pmd/shared_rxq_fwd.c
Signature · 1 line
2.33.0