From 86ba409707b11089dc6e59f7b09d8f89c06aed9d Mon Sep 17 00:00:00 2001 From: Xavier Simonart Date: Sat, 14 Apr 2018 17:19:41 +0200 Subject: Add support for reception of jumbo frames Jumbo frames are now supported through the addition of a "mtu" parameter of the port in the config file. Setting the mtu to a value higher than 1500 bytes will enable the reception of jumbo frames. In addition, the rte_eth_dev_set_mtu is now set for all pmds. Finally, setting mbuf_size does not set MEMPOOL_F_NO_SPREAD anymore. This option was only used for pure debugging. Big packets can be received using two ways - Using multiple "small" mbufs, i.e. around 2K. This is the default. - Using one big mbuf holding the whole packet. This can be enabled by setting a parameter mbuf_size in the receiving core configuration Change-Id: Idd60ad31f41c89f9522dff4d894af2696b7a2ea1 Signed-off-by: Xavier Simonart --- VNFs/DPPD-PROX/main.c | 96 +++++++++++++++++++++++++++--------------- VNFs/DPPD-PROX/prox_args.c | 14 ++++++ VNFs/DPPD-PROX/prox_port_cfg.c | 10 ++--- 3 files changed, 81 insertions(+), 39 deletions(-) diff --git a/VNFs/DPPD-PROX/main.c b/VNFs/DPPD-PROX/main.c index 2c8517f0..931b30c5 100644 --- a/VNFs/DPPD-PROX/main.c +++ b/VNFs/DPPD-PROX/main.c @@ -285,6 +285,7 @@ static void configure_if_tx_queues(struct task_args *targ, uint8_t socket) static void configure_if_rx_queues(struct task_args *targ, uint8_t socket) { + struct prox_port_cfg *port; for (int i = 0; i < targ->nb_rxports; i++) { uint8_t if_port = targ->rx_port_queue[i].port; @@ -293,15 +294,23 @@ static void configure_if_rx_queues(struct task_args *targ, uint8_t socket) } PROX_PANIC(!prox_port_cfg[if_port].active, "Port %u not used, aborting...\n", if_port); + port = &prox_port_cfg[if_port]; - if(prox_port_cfg[if_port].rx_ring[0] != '\0') { - prox_port_cfg[if_port].n_rxq = 0; + if(port->rx_ring[0] != '\0') { + port->n_rxq = 0; } + // Force multi segment support if mbuf size is not big enough. + // This is usually the case when setting a big mtu size i.e. enabling jumbo frames. + uint16_t max_frame_size = port->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE; + if (max_frame_size + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM > targ->mbuf_size) { + targ->task_init->flag_features &= ~TASK_FEATURE_TXQ_FLAGS_NOMULTSEGS; + plog_info("\t\tDisabling No MultSegs on port %u as %lu > %u\n", if_port, max_frame_size + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM, targ->mbuf_size); + } targ->rx_port_queue[i].queue = prox_port_cfg[if_port].n_rxq; - prox_port_cfg[if_port].pool[targ->rx_port_queue[i].queue] = targ->pool; - prox_port_cfg[if_port].pool_size[targ->rx_port_queue[i].queue] = targ->nb_mbuf - 1; - prox_port_cfg[if_port].n_rxq++; + port->pool[targ->rx_port_queue[i].queue] = targ->pool; + port->pool_size[targ->rx_port_queue[i].queue] = targ->nb_mbuf - 1; + port->n_rxq++; int dsocket = prox_port_cfg[if_port].socket; if (dsocket != -1 && dsocket != socket) { @@ -319,8 +328,8 @@ static void configure_if_queues(void) while (core_targ_next(&lconf, &targ, 0) == 0) { socket = rte_lcore_to_socket_id(lconf->id); - configure_if_tx_queues(targ, socket); configure_if_rx_queues(targ, socket); + configure_if_tx_queues(targ, socket); } } @@ -578,6 +587,52 @@ static void shuffle_mempool(struct rte_mempool* mempool, uint32_t nb_mbuf) prox_free(pkts); } +static void set_mbuf_size(struct task_args *targ) +{ + /* mbuf size can be set + * - from config file (highest priority, overwriting any other config) - should only be used as workaround + * - through each 'mode', overwriting the default mbuf_size + * - defaulted to MBUF_SIZE i.e. 1518 Bytes + * Except if set explicitely, ensure that size is big enough for vmxnet3 driver + */ + if (targ->mbuf_size_set_explicitely) + return; + + if (targ->task_init->mbuf_size != 0) { + /* mbuf_size not set through config file but set through mode */ + targ->mbuf_size = targ->task_init->mbuf_size; + } + + struct prox_port_cfg *port; + uint16_t max_frame_size = 0; + for (int i = 0; i < targ->nb_rxports; i++) { + uint8_t if_port = targ->rx_port_queue[i].port; + + if (if_port == OUT_DISCARD) { + continue; + } + port = &prox_port_cfg[if_port]; + if (max_frame_size < port->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE) + max_frame_size = port->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE; + + if (strcmp(port->short_name, "vmxnet3") == 0) { + if (targ->mbuf_size < MBUF_SIZE + RTE_PKTMBUF_HEADROOM) + targ->mbuf_size = MBUF_SIZE + RTE_PKTMBUF_HEADROOM; + if (targ->mbuf_size < max_frame_size) + targ->mbuf_size = max_frame_size + RTE_PKTMBUF_HEADROOM; + } + } + if (max_frame_size) { + // i40e supports a maximum of 5 descriptors chained + uint16_t required_mbuf_size = RTE_ALIGN(max_frame_size / 5, 128) + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM; + if (required_mbuf_size > targ->mbuf_size) { + targ->mbuf_size = required_mbuf_size; + plog_info("\t\tSetting mbuf_size to %u to support frame_size %u (mtu %u)\n", targ->mbuf_size, max_frame_size, port->mtu); + } + } + +} + static void setup_mempools_unique_per_socket(void) { uint32_t flags = 0; @@ -595,11 +650,7 @@ static void setup_mempools_unique_per_socket(void) uint8_t socket = rte_lcore_to_socket_id(lconf->id); PROX_ASSERT(socket < MAX_SOCKETS); - if (targ->mbuf_size_set_explicitely) - flags = MEMPOOL_F_NO_SPREAD; - if ((!targ->mbuf_size_set_explicitely) && (targ->task_init->mbuf_size != 0)) { - targ->mbuf_size = targ->task_init->mbuf_size; - } + set_mbuf_size(targ); if (targ->rx_port_queue[0].port != OUT_DISCARD) { struct prox_port_cfg* port_cfg = &prox_port_cfg[targ->rx_port_queue[0].port]; PROX_ASSERT(targ->nb_mbuf != 0); @@ -616,10 +667,6 @@ static void setup_mempools_unique_per_socket(void) PROX_PANIC(mbuf_size[socket] != targ->mbuf_size, "all mbuf_size must have the same size if using a unique mempool per socket\n"); } - if ((!targ->mbuf_size_set_explicitely) && (strcmp(port_cfg->short_name, "vmxnet3") == 0)) { - if (mbuf_size[socket] < MBUF_SIZE + RTE_PKTMBUF_HEADROOM) - mbuf_size[socket] = MBUF_SIZE + RTE_PKTMBUF_HEADROOM; - } } } for (int i = 0 ; i < MAX_SOCKETS; i++) { @@ -668,24 +715,7 @@ static void setup_mempool_for_rx_task(struct lcore_cfg *lconf, struct task_args char memzone_name[64]; char name[64]; - /* mbuf size can be set - * - from config file (highest priority, overwriting any other config) - should only be used as workaround - * - through each 'mode', overwriting the default mbuf_size - * - defaulted to MBUF_SIZE i.e. 1518 Bytes - * Except is set expliciteky, ensure that size is big enough for vmxnet3 driver - */ - if (targ->mbuf_size_set_explicitely) { - flags = MEMPOOL_F_NO_SPREAD; - /* targ->mbuf_size already set */ - } - else if (targ->task_init->mbuf_size != 0) { - /* mbuf_size not set through config file but set through mode */ - targ->mbuf_size = targ->task_init->mbuf_size; - } - else if (strcmp(port_cfg->short_name, "vmxnet3") == 0) { - if (targ->mbuf_size < MBUF_SIZE + RTE_PKTMBUF_HEADROOM) - targ->mbuf_size = MBUF_SIZE + RTE_PKTMBUF_HEADROOM; - } + set_mbuf_size(targ); /* allocate memory pool for packets */ PROX_ASSERT(targ->nb_mbuf != 0); diff --git a/VNFs/DPPD-PROX/prox_args.c b/VNFs/DPPD-PROX/prox_args.c index 08f27e9e..53223cad 100644 --- a/VNFs/DPPD-PROX/prox_args.c +++ b/VNFs/DPPD-PROX/prox_args.c @@ -546,6 +546,20 @@ static int get_port_cfg(unsigned sindex, char *str, void *data) } cfg->port_conf.rxmode.hw_strip_crc = val; } + else if (STR_EQ(str, "mtu size")) { + uint32_t val; + if (parse_int(&val, pkey)) { + return -1; + } + if (val) { + cfg->mtu = val; + if (cfg->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN > ETHER_MAX_LEN) { + cfg->port_conf.rxmode.max_rx_pkt_len = cfg->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + 2 * PROX_VLAN_TAG_SIZE; + cfg->port_conf.rxmode.jumbo_frame = 1; + } + } + } + else if (STR_EQ(str, "rss")) { uint32_t val; if (parse_bool(&val, pkey)) { diff --git a/VNFs/DPPD-PROX/prox_port_cfg.c b/VNFs/DPPD-PROX/prox_port_cfg.c index c4787b1e..c00948ad 100644 --- a/VNFs/DPPD-PROX/prox_port_cfg.c +++ b/VNFs/DPPD-PROX/prox_port_cfg.c @@ -294,12 +294,10 @@ static void init_port(struct prox_port_cfg *port_cfg) port_cfg->socket, port_cfg->n_rxd); dummy_pool_name[0]++; } else { - // Most pmd do not support setting mtu yet... - if (!strcmp(port_cfg->short_name, "ixgbe")) { - plog_info("\t\tSetting MTU size to %u for port %u ...\n", port_cfg->mtu, port_id); - ret = rte_eth_dev_set_mtu(port_id, port_cfg->mtu); - PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_set_mtu() failed on port %u: error %d\n", port_id, ret); - } + // Most pmd should now support setting mtu + plog_info("\t\tSetting MTU size to %u for port %u ...\n", port_cfg->mtu, port_id); + ret = rte_eth_dev_set_mtu(port_id, port_cfg->mtu); + PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_set_mtu() failed on port %u: error %d\n", port_id, ret); if (port_cfg->n_txq == 0) { /* not sending on this port */ -- cgit 1.2.3-korg