net/netvsc: allow setting rx and tx copy break
PATCH v2 1/2 net/netvsc: allow setting rx and tx copy break
From: Stephen Hemminger <[email protected]>
The values for Rx and Tx copy break should be tunable rather than hard coded constants.
The rx_copybreak sets the threshold where the driver uses an external mbuf to avoid having to copy data. Setting 0 for copybreak will cause driver to always create an external mbuf. Setting a value greater than the MTU would prevent it from ever making an external mbuf and always copy. The default value is 256 (bytes).
Likewise the tx_copybreak sets the threshold where the driver aggregates multiple small packets into one request. If tx_copybreak is 0 then each packet goes as a VMBus request (no copying). If tx_copybreak is set larger than the MTU, then all packets smaller than the chunk size of the VMBus send buffer will be copied; larger packets always have to go as a single direct request. The default value is 512 (bytes).
--- doc/guides/nics/netvsc.rst | 17 ++++++++++++ drivers/net/netvsc/hn_ethdev.c | 48 +++++++++++++++++++++++++--------- drivers/net/netvsc/hn_rxtx.c | 8 +++--- drivers/net/netvsc/hn_var.h | 5 ++++ 4 files changed, 60 insertions(+), 18 deletions(-)
doc/guides/nics/netvsc.rst +17 -0
@@ -116,3 +116,20 @@ The user can specify below argument in devargs. values save CPU cycles. This parameter is in microseconds. If the value is too large or too small it will be ignored by the host. (Default: 50) + +#. ``rx_copybreak``: + + The rx_copybreak sets the threshold where the driver uses an external + mbuf to avoid having to copy data. Setting 0 for copybreak will cause + driver to always create an external mbuf. Setting a value greater than + the MTU would prevent it from ever making an external mbuf and always + copy. The default value is 256 (bytes). + +#. ``tx_copybreak``: + + The tx_copybreak sets the threshold where the driver aggregates + multiple small packets into one request. If tx_copybreak is 0 then + each packet goes as a VMBus request (no copying). If tx_copybreak is + set larger than the MTU, then all packets smaller than the chunk size + of the VMBus send buffer will be copied; larger packets always have to + go as a single direct request. The default value is 512 (bytes).
drivers/net/netvsc/hn_ethdev.c +35 -13
92 lines not on this page · raw message
drivers/net/netvsc/hn_rxtx.c +3 -5
@@ -40,9 +40,6 @@ (sizeof(struct vmbus_chanpkt_hdr) + sizeof(struct hn_nvs_rndis))#define HN_TXD_CACHE_SIZE 32/* per cpu tx_descriptor pool cache */ -#define HN_TXCOPY_THRESHOLD 512 - -#define HN_RXCOPY_THRESHOLD 256#define HN_RXQ_EVENT_DEFAULT 2048struct hn_rxinfo {
@@ -568,7 +565,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,* For large packets, avoid copy if possible but need to keep * some space available in receive area for later packets. */ -if (dlen >=HN_RXCOPY_THRESHOLD && +if (dlen > hv->rx_copybreak && (uint32_t )rte_atomic32_read (&rxq->rxbuf_outstanding) < hv->rxbuf_section_cnt /2 ) {struct rte_mbuf_ext_shared_info *shinfo;
@@ -1516,7 +1513,8 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)break ;/* For small packets aggregate them in chimney buffer */ -if (m->pkt_len <HN_TXCOPY_THRESHOLD && pkt_size <= txq->agg_szmax) { +if (m->pkt_len <= hv->tx_copybreak && + pkt_size <= txq->agg_szmax) {/* If this packet will not fit, then flush */ if (txq->agg_pktleft ==0 ||RTE_ALIGN (pkt_size, txq->agg_align) > txq->agg_szleft) {
drivers/net/netvsc/hn_var.h +5 -0
@@ -23,6 +23,9 @@/* Host monitor interval */ #define HN_CHAN_LATENCY_NS 50000 +#define HN_TXCOPY_THRESHOLD 512 +#define HN_RXCOPY_THRESHOLD 256 +/* Buffers need to be aligned */ #ifndef PAGE_SIZE #define PAGE_SIZE 4096
@@ -114,6 +117,7 @@ struct hn_data {struct rte_mem_resource *rxbuf_res;/* UIO resource for Rx */ uint32_t rxbuf_section_cnt;/* # of Rx sections */ +uint32_t rx_copybreak;uint16_t max_queues;/* Max available queues */ uint16_t num_queues;uint64_t rss_offloads;
@@ -122,6 +126,7 @@ struct hn_data {struct rte_mem_resource *chim_res;/* UIO resource for Tx */ struct rte_bitmap *chim_bmap;/* Send buffer map */ void *chim_bmem; +uint32_t tx_copybreak;uint32_t chim_szmax;/* Max size per buffer */ uint32_t chim_cnt;/* Max packets per buffer */
Signature · 1 line
2.25.1
PATCH v2 2/2 net/netvsc: introduce driver parameter to control the use of external mbuf on receiving data
From: Long Li <[email protected]>
When receiving packets, netvsp puts data in a buffer mapped through UIO. Depending on packet size, netvsc may attach the buffer as an external mbuf. This is not a problem if this mbuf is consumed in the application, and the application can correctly read data out of an external mbuf.
However, there are two problems with data in an external mbuf.
1. Due to the limitation of the kernel UIO implementation, physical address of this external buffer is not exposed to the user-mode. If this mbuf is passed to another driver, the other driver is unable to map this buffer to iova.
2. Some DPDK applications are not aware of external mbuf, and may bug when they receive an mbuf with external buffer attached.
Introduce a driver parameter "rx_extmbuf_enable" to control if netvsc should use external mbuf for receiving packets. The default value is 0. (netvsc doesn't use external mbuf, it always allocates mbuf and copy data to mbuf) A non-zero value tells netvsc to attach external buffers to mbuf on receiving packets, thus avoid copying memory.
--- doc/guides/nics/netvsc.rst | 8 ++++++++ drivers/net/netvsc/hn_ethdev.c | 7 +++++++ drivers/net/netvsc/hn_rxtx.c | 2 +- drivers/net/netvsc/hn_var.h | 3 +++ 4 files changed, 19 insertions(+), 1 deletion(-)
doc/guides/nics/netvsc.rst +8 -0
@@ -133,3 +133,11 @@ The user can specify below argument in devargs. set larger than the MTU, then all packets smaller than the chunk size of the VMBus send buffer will be copied; larger packets always have to go as a single direct request. The default value is 512 (bytes). + +#. ``rx_extmbuf_enable``: + The rx_extmbuf_enable is used to control if netvsc should use external + mbuf for receiving packets. The default value is 0. (netvsc doesn't use + external mbuf, it always allocates mbuf and copy received data to mbuf) + A non-zero value tells netvsc to attach external buffers to mbuf on + receiving packets, thus avoid copying memory. Use of external buffers + requires the application is able to read data from external mbuf.
drivers/net/netvsc/hn_ethdev.c +7 -0
@@ -48,6 +48,7 @@#define NETVSC_ARG_LATENCY "latency"#define NETVSC_ARG_RXBREAK "rx_copybreak"#define NETVSC_ARG_TXBREAK "tx_copybreak" +#define NETVSC_ARG_RX_EXTMBUF_ENABLE "rx_extmbuf_enable"struct hn_xstats_name_off {char name[RTE_ETH_XSTATS_NAME_SIZE ];
@@ -164,6 +165,10 @@ static int hn_set_parameter(const char *key, const char *value, void *opaque) hv->tx_copybreak = v;PMD_DRV_LOG (DEBUG ,"tx copy break set to %u" , hv->tx_copybreak); + }else if (!strcmp (key,NETVSC_ARG_RX_EXTMBUF_ENABLE )) { + hv->rx_extmbuf_enable = v; +PMD_DRV_LOG (DEBUG ,"rx extmbuf enable set to %u" , + hv->rx_extmbuf_enable); }return 0 ;
@@ -178,6 +183,7 @@ static int hn_parse_args(const struct rte_eth_dev *dev)NETVSC_ARG_LATENCY ,NETVSC_ARG_RXBREAK ,NETVSC_ARG_TXBREAK , +NETVSC_ARG_RX_EXTMBUF_ENABLE , NULL };struct rte_kvargs *kvlist;
@@ -987,6 +993,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev) hv->latency =HN_CHAN_LATENCY_NS ; hv->rx_copybreak =HN_RXCOPY_THRESHOLD ; hv->tx_copybreak =HN_TXCOPY_THRESHOLD ; + hv->rx_extmbuf_enable =HN_RX_EXTMBUF_ENABLE ; hv->max_queues =1 ;rte_rwlock_init (&hv->vf_lock);
drivers/net/netvsc/hn_rxtx.c +1 -1
@@ -565,7 +565,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,* For large packets, avoid copy if possible but need to keep * some space available in receive area for later packets. */ -if (dlen > hv->rx_copybreak && +if (hv->rx_extmbuf_enable && dlen > hv->rx_copybreak && (uint32_t )rte_atomic32_read (&rxq->rxbuf_outstanding) < hv->rxbuf_section_cnt /2 ) {struct rte_mbuf_ext_shared_info *shinfo;
drivers/net/netvsc/hn_var.h +3 -0
@@ -26,6 +26,8 @@#define HN_TXCOPY_THRESHOLD 512#define HN_RXCOPY_THRESHOLD 256 +#define HN_RX_EXTMBUF_ENABLE 0 +/* Buffers need to be aligned */ #ifndef PAGE_SIZE #define PAGE_SIZE 4096
@@ -118,6 +120,7 @@ struct hn_data {struct rte_mem_resource *rxbuf_res;/* UIO resource for Rx */ uint32_t rxbuf_section_cnt;/* # of Rx sections */ uint32_t rx_copybreak; +uint32_t rx_extmbuf_enable;uint16_t max_queues;/* Max available queues */ uint16_t num_queues;uint64_t rss_offloads;
Signature · 1 line
2.25.1
Quoted 21 lines · Long Li
From: Stephen Hemminger <[email protected]>
The values for Rx and Tx copy break should be tunable rather than hard coded constants.
The
rx_copybreaksets the threshold where the driver uses an external mbuf to avoid having to copy data. Setting 0 for copybreak will cause driver to always create an external mbuf. Setting a value greater than the MTU would prevent it from ever making an external mbuf and always copy. The default value is 256 (bytes).Likewise the
tx_copybreaksets the threshold where the driver aggregates multiple small packets into one request. Iftx_copybreakis 0 then each packet goes as a VMBus request (no copying). Iftx_copybreakis set larger than the MTU, then all packets smaller than the chunk size of the VMBus send buffer will be copied; larger packets always have to go as a single direct request. The default value is 512 (bytes).Signed-off-by Stephen Hemminger <[email protected]>Signed-off-by Long Li <[email protected]>
<...>
drivers/net/netvsc/hn_ethdev.c static int hn_parse_args(const struct rte_eth_dev *dev) · line 202
Quoted 12 lines
drivers/net/netvsc/hn_ethdev.c +5
-3@@ -181,9 +195,14 @@ static int hn_parse_args(const struct rte_eth_dev *dev)return -EINVAL ; } - ret =rte_kvargs_process (kvlist,"latency" , hn_set_latency, hv); -if (ret) -PMD_DRV_LOG (ERR ,"Unable to process latency arg\n" ); +for (i =0 ; i <sizeof (valid_keys) /sizeof (valid_keys[0 ]) -1 ; i++) { + ret =rte_kvargs_process (kvlist, valid_keys[i], + hn_set_parameter, hv); +if (ret) { +PMD_DRV_LOG (ERR ,"Unable to process latency arg\n" );
Need to update the log, it is not only 'latency' anymore.
drivers/net/netvsc/hn_ethdev.c static int hn_parse_args(const struct rte_eth_dev *dev) · line 205
Quoted 3 lines
drivers/net/netvsc/hn_ethdev.c +3
-0+break ; + } + }
Since there is single callback for all args, and there is already a 'key' check in the callback function, why not call the 'rte_kvargs_process()' with NULL argument and drop the for loop:
ret = rte_kvargs_process(kvlist, NULL, hn_set_parameter, hv);
Can you also register the devargs in .c file:
'RTE_PMD_REGISTER_PARAM_STRING'
This is to get PMD supported devargs from .so, using "./usertools/dpdk-pmdinfo.py".
Thanks,
ferruh
Quoted 54 lines
Subject: Re: [dpdk-dev] [PATCH V2 1/2] net/netvsc: allow setting rx and tx copy break
Quoted 21 lines · Long Li
From: Stephen Hemminger <[email protected]>
The values for Rx and Tx copy break should be tunable rather than hard coded constants.
The
rx_copybreaksets the threshold where the driver uses an external mbuf to avoid having to copy data. Setting 0 for copybreak will cause driver to always create an external mbuf. Setting a value greater than the MTU would prevent it from ever making an external mbuf and always copy. The default value is 256 (bytes).Likewise the
tx_copybreaksets the threshold where the driver aggregates multiple small packets into one request. Iftx_copybreakis 0 then each packet goes as a VMBus request (no copying).
Iftx_copybreakis set larger than the MTU, then all packets smaller than the chunk size of the VMBus send buffer will be copied; larger packets always have to go as a single direct request. The default value is 512 (bytes).Signed-off-by Stephen Hemminger <[email protected]>Signed-off-by Long Li <[email protected]><...>
Review static int hn_parse_args(const struct rte_eth_dev
Quoted 1 line
(quoted diff) +0
-0@@ -181,9 +195,14 @@ static int hn_parse_args(const struct rte_eth_dev*dev)
drivers/net/netvsc/hn_ethdev.c static int hn_parse_args(const struct rte_eth_dev *dev)
Quoted 11 lines
drivers/net/netvsc/hn_ethdev.c +5
-3return -EINVAL ; } - ret =rte_kvargs_process (kvlist,"latency" , hn_set_latency, hv); -if (ret) -PMD_DRV_LOG (ERR ,"Unable to process latency arg\n" ); +for (i =0 ; i <sizeof (valid_keys) /sizeof (valid_keys[0 ]) -1 ; i++) { + ret =rte_kvargs_process (kvlist, valid_keys[i], + hn_set_parameter, hv); +if (ret) { + PMD_DRV_LOG(ERR, "Unable to process latencyarg\n");
Need to update the log, it is not only 'latency' anymore.
drivers/net/netvsc/hn_ethdev.c static int hn_parse_args(const struct rte_eth_dev *dev) · line 205
Quoted 3 lines
drivers/net/netvsc/hn_ethdev.c +3
-0+break ; + } + }Since there is single callback for all args, and there is already a 'key' check in the callback function, why not call the '
rte_kvargs_process()' with NULL argument and drop the for loop:
ret =rte_kvargs_process(kvlist, NULL, hn_set_parameter, hv);
Quoted 4 lines
Can you also register the devargs in .c file:
'RTE_PMD_REGISTER_PARAM_STRING'
This is to get PMD supported devargs from .so, using "./usertools/dpdk-pmdinfo.py".
I have sent V3 to address comments.
Thanks!
Long
Quoted 3 lines
Thanks,
ferruh