2 // Copyright (c) 2010-2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
19 #include <rte_version.h>
20 #include <rte_eth_ring.h>
22 #if (RTE_VERSION >= RTE_VERSION_NUM(17,11,0,0))
23 #include <rte_bus_vdev.h>
25 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,2))
28 #if (RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0))
29 #include <rte_eth_null.h>
34 #include "prox_port_cfg.h"
35 #include "prox_globals.h"
41 #include "prox_cksum.h"
42 #include "stats_irq.h"
43 #include "prox_compat.h"
45 struct prox_port_cfg prox_port_cfg[PROX_MAX_PORTS];
48 int prox_nb_active_ports(void)
51 for (uint32_t i = 0; i < PROX_MAX_PORTS; ++i) {
52 ret += prox_port_cfg[i].active;
57 int prox_last_port_active(void)
60 for (uint32_t i = 0; i < PROX_MAX_PORTS; ++i) {
61 if (prox_port_cfg[i].active) {
68 #if RTE_VERSION >= RTE_VERSION_NUM(17,11,0,0)
69 static int lsc_cb(__attribute__((unused)) uint16_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
70 __attribute__((unused)) void *ret_param)
72 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
73 static int lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
74 __attribute__((unused)) void *ret_param)
76 static void lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param)
80 if (RTE_ETH_EVENT_INTR_LSC != type) {
81 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
88 rte_atomic32_inc(&lsc);
90 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
95 struct prox_pktmbuf_reinit_args {
96 struct rte_mempool *mp;
97 struct lcore_cfg *lconf;
100 /* standard mbuf initialization procedure */
101 void prox_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigned i)
103 struct rte_mbuf *mbuf = _m;
105 #if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
106 mbuf->tx_offload = CALC_TX_OL(sizeof(struct ether_hdr), sizeof(struct ipv4_hdr));
108 mbuf->pkt.vlan_macip.f.l2_len = sizeof(struct ether_hdr);
109 mbuf->pkt.vlan_macip.f.l3_len = sizeof(struct ipv4_hdr);
112 rte_pktmbuf_init(mp, opaque_arg, mbuf, i);
115 void prox_pktmbuf_reinit(void *arg, void *start, __attribute__((unused)) void *end, uint32_t idx)
117 struct prox_pktmbuf_reinit_args *init_args = arg;
121 obj += init_args->mp->header_size;
122 m = (struct rte_mbuf*)obj;
124 prox_pktmbuf_init(init_args->mp, init_args->lconf, obj, idx);
127 #define CONFIGURE_TX_OFFLOAD(flag) \
128 if (port_cfg->requested_tx_offload & flag) {\
129 if (port_cfg->disabled_tx_offload & flag) {\
130 plog_info("\t\t%s disabled by configuration\n", #flag);\
131 port_cfg->requested_tx_offload &= ~flag;\
132 } else if (port_cfg->dev_info.tx_offload_capa & flag) {\
133 port_cfg->port_conf.txmode.offloads |= flag;\
134 plog_info("\t\t%s enabled on port\n", #flag);\
135 } else if (port_cfg->dev_info.tx_queue_offload_capa & flag) {\
136 port_cfg->tx_conf.offloads |= flag;\
137 plog_info("\t\t%s enabled on queue\n", #flag);\
139 port_cfg->requested_tx_offload &= ~flag;\
140 plog_info("\t\t%s disabled as neither port or queue supports it\n", #flag);\
143 plog_info("\t\t%s disabled\n", #flag);\
146 #define CONFIGURE_RX_OFFLOAD(flag) \
147 if (port_cfg->requested_rx_offload & flag) {\
148 if (port_cfg->dev_info.rx_offload_capa & flag) {\
149 port_cfg->port_conf.rxmode.offloads |= flag;\
150 plog_info("\t\t%s enabled on port\n", #flag);\
151 } else if (port_cfg->dev_info.rx_queue_offload_capa & flag) {\
152 port_cfg->rx_conf.offloads |= flag;\
153 plog_info("\t\t%s enabled on queue\n", #flag);\
155 port_cfg->requested_rx_offload &= ~flag;\
156 plog_info("\t\t%s disabled as neither port or queue supports it\n", #flag);\
159 plog_info("\t\t%s disabled\n", #flag);\
163 /* initialize rte devices and check the number of available ports */
164 void init_rte_dev(int use_dummy_devices)
166 uint8_t nb_ports, port_id_max;
168 struct rte_eth_dev_info dev_info;
169 const struct rte_pci_device *pci_dev;
171 nb_ports = rte_eth_dev_count();
172 /* get available ports configuration */
173 PROX_PANIC(use_dummy_devices && nb_ports, "Can't use dummy devices while there are also real ports\n");
175 if (use_dummy_devices) {
176 #if (RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0))
177 nb_ports = prox_last_port_active() + 1;
178 plog_info("Creating %u dummy devices\n", nb_ports);
180 char port_name[32] = "0dummy_dev";
181 for (uint32_t i = 0; i < nb_ports; ++i) {
182 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
183 rte_vdev_init(port_name, "size=ETHER_MIN_LEN,copy=0");
185 eth_dev_null_create(port_name, 0, ETHER_MIN_LEN, 0);
190 PROX_PANIC(use_dummy_devices, "Can't use dummy devices\n");
193 else if (prox_last_port_active() != -1) {
194 PROX_PANIC(nb_ports == 0, "\tError: DPDK could not find any port\n");
195 plog_info("\tDPDK has found %u ports\n", nb_ports);
198 if (nb_ports > PROX_MAX_PORTS) {
199 plog_warn("\tWarning: I can deal with at most %u ports."
200 " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
202 nb_ports = PROX_MAX_PORTS;
204 port_id_max = nb_ports - 1;
205 port_id_last = prox_last_port_active();
206 PROX_PANIC(port_id_last > port_id_max,
207 "\tError: invalid port(s) specified, last port index active: %d (max index is %d)\n",
208 port_id_last, port_id_max);
210 /* Assign ports to PROX interfaces & Read max RX/TX queues per port */
211 for (uint8_t port_id = 0; port_id < nb_ports; ++port_id) {
212 /* skip ports that are not enabled */
213 if (!prox_port_cfg[port_id].active) {
216 plog_info("\tGetting info for rte dev %u\n", port_id);
217 rte_eth_dev_info_get(port_id, &dev_info);
218 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
219 port_cfg->socket = -1;
221 memcpy(&port_cfg->dev_info, &dev_info, sizeof(struct rte_eth_dev_info));
222 port_cfg->max_txq = dev_info.max_tx_queues;
223 port_cfg->max_rxq = dev_info.max_rx_queues;
224 port_cfg->max_rx_pkt_len = dev_info.max_rx_pktlen;
225 port_cfg->min_rx_bufsize = dev_info.min_rx_bufsize;
227 #if RTE_VERSION < RTE_VERSION_NUM(18,5,0,0)
228 pci_dev = dev_info.pci_dev;
230 pci_dev = RTE_DEV_TO_PCI(dev_info.device);
235 snprintf(port_cfg->pci_addr, sizeof(port_cfg->pci_addr),
236 "%04x:%02x:%02x.%1x", pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function);
237 strncpy(port_cfg->driver_name, dev_info.driver_name, sizeof(port_cfg->driver_name));
238 plog_info("\tPort %u : driver='%s' tx_queues=%d rx_queues=%d\n", port_id, !strcmp(port_cfg->driver_name, "")? "null" : port_cfg->driver_name, port_cfg->max_txq, port_cfg->max_rxq);
240 if (strncmp(port_cfg->driver_name, "rte_", 4) == 0) {
241 strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
242 } else if (strncmp(port_cfg->driver_name, "net_", 4) == 0) {
243 strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
245 strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name, sizeof(port_cfg->short_name));
248 if ((ptr = strstr(port_cfg->short_name, "_pmd")) != NULL) {
252 /* Try to find the device's numa node */
254 snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/numa_node", port_cfg->pci_addr);
255 FILE* numa_node_fd = fopen(buf, "r");
257 if (fgets(buf, sizeof(buf), numa_node_fd) == NULL) {
258 plog_warn("Failed to read numa_node for device %s\n", port_cfg->pci_addr);
260 port_cfg->socket = strtol(buf, 0, 0);
261 if (port_cfg->socket == -1) {
262 plog_warn("System did not report numa_node for device %s\n", port_cfg->pci_addr);
264 fclose(numa_node_fd);
267 // In DPDK 18.08 vmxnet3 reports it supports IPV4 checksum, but packets does not go through when IPv4 cksum is enabled
268 if ((!strcmp(port_cfg->short_name, "vmxnet3")) && (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {
269 plog_info("\t\tDisabling IPV4 cksum on vmxnet3\n");
270 port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_IPV4_CKSUM;
272 if ((!strcmp(port_cfg->short_name, "vmxnet3")) && (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) {
273 plog_info("\t\tDisabling UDP cksum on vmxnet3\n");
274 port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_UDP_CKSUM;
279 /* Create rte ring-backed devices */
280 uint8_t init_rte_ring_dev(void)
282 uint8_t nb_ring_dev = 0;
284 for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
285 /* skip ports that are not enabled */
286 if (!prox_port_cfg[port_id].active) {
289 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
290 if (port_cfg->rx_ring[0] != '\0') {
291 plog_info("\tRing-backed port %u: rx='%s' tx='%s'\n", port_id, port_cfg->rx_ring, port_cfg->tx_ring);
293 struct rte_ring* rx_ring = rte_ring_lookup(port_cfg->rx_ring);
294 PROX_PANIC(rx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->rx_ring, port_id);
295 struct rte_ring* tx_ring = rte_ring_lookup(port_cfg->tx_ring);
296 PROX_PANIC(tx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->tx_ring, port_id);
298 int ret = rte_eth_from_rings(port_cfg->name, &rx_ring, 1, &tx_ring, 1, rte_socket_id());
299 PROX_PANIC(ret != 0, "Failed to create eth_dev from rings for port %d\n", port_id);
301 port_cfg->port_conf.intr_conf.lsc = 0; /* Link state interrupt not supported for ring-backed ports */
310 static void init_port(struct prox_port_cfg *port_cfg)
312 static char dummy_pool_name[] = "0_dummy";
313 struct rte_eth_link link;
317 port_id = port_cfg - prox_port_cfg;
318 plog_info("\t*** Initializing port %u ***\n", port_id);
319 plog_info("\t\tPort name is set to %s\n", port_cfg->name);
320 plog_info("\t\tPort max RX/TX queue is %u/%u\n", port_cfg->max_rxq, port_cfg->max_txq);
321 plog_info("\t\tPort driver is %s\n", port_cfg->driver_name);
322 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0)
323 plog_info("\t\tSupported speed mask = 0x%x\n", port_cfg->dev_info.speed_capa);
326 PROX_PANIC(port_cfg->n_rxq == 0 && port_cfg->n_txq == 0,
327 "\t\t port %u is enabled but no RX or TX queues have been configured", port_id);
329 if (port_cfg->n_rxq == 0) {
330 /* not receiving on this port */
331 plog_info("\t\tPort %u had no RX queues, setting to 1\n", port_id);
333 uint32_t mbuf_size = TX_MBUF_SIZE;
334 plog_info("\t\tAllocating dummy memory pool on socket %u with %u elements of size %u\n",
335 port_cfg->socket, port_cfg->n_rxd, mbuf_size);
336 port_cfg->pool[0] = rte_mempool_create(dummy_pool_name, port_cfg->n_rxd, mbuf_size,
338 sizeof(struct rte_pktmbuf_pool_private),
339 rte_pktmbuf_pool_init, NULL,
340 prox_pktmbuf_init, 0,
341 port_cfg->socket, 0);
342 PROX_PANIC(port_cfg->pool[0] == NULL, "Failed to allocate dummy memory pool on socket %u with %u elements\n",
343 port_cfg->socket, port_cfg->n_rxd);
344 dummy_pool_name[0]++;
346 // Most pmd should now support setting mtu
347 if (port_cfg->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN > port_cfg->max_rx_pkt_len) {
348 plog_info("\t\tMTU is too big for the port, reducing MTU from %d to %d\n", port_cfg->mtu, port_cfg->max_rx_pkt_len);
349 port_cfg->mtu = port_cfg->max_rx_pkt_len;
351 plog_info("\t\tSetting MTU size to %u for port %u ...\n", port_cfg->mtu, port_id);
352 ret = rte_eth_dev_set_mtu(port_id, port_cfg->mtu);
354 plog_err("\t\t\trte_eth_dev_set_mtu() failed on port %u: error %d\n", port_id, ret);
356 if (port_cfg->n_txq == 0) {
357 /* not sending on this port */
358 plog_info("\t\tPort %u had no TX queues, setting to 1\n", port_id);
363 if (port_cfg->n_rxq > 1) {
364 // Enable RSS if multiple receive queues
365 port_cfg->port_conf.rxmode.mq_mode |= ETH_MQ_RX_RSS;
366 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key = toeplitz_init_key;
367 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key_len = TOEPLITZ_KEY_LEN;
368 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
369 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IPV4|ETH_RSS_NONFRAG_IPV4_UDP;
371 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IPV4|ETH_RSS_NONF_IPV4_UDP;
375 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
376 plog_info("\t\tRX offload capa = 0x%lx = ", port_cfg->dev_info.rx_offload_capa);
377 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP)
378 plog_info("VLAN STRIP | ");
379 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM)
380 plog_info("IPV4 CKSUM | ");
381 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM)
382 plog_info("UDP CKSUM | ");
383 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)
384 plog_info("TCP CKSUM | ");
385 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO)
386 plog_info("TCP LRO | ");
387 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP)
388 plog_info("QINQ STRIP | ");
389 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
390 plog_info("OUTER_IPV4_CKSUM | ");
391 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_MACSEC_STRIP)
392 plog_info("MACSEC STRIP | ");
393 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_HEADER_SPLIT)
394 plog_info("HEADER SPLIT | ");
395 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_FILTER)
396 plog_info("VLAN FILTER | ");
397 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_EXTEND)
398 plog_info("VLAN EXTEND | ");
399 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME)
400 plog_info("JUMBO FRAME | ");
401 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_CRC_STRIP)
402 plog_info("CRC STRIP | ");
403 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCATTER)
404 plog_info("SCATTER | ");
405 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP)
406 plog_info("TIMESTAMP | ");
407 if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY)
408 plog_info("SECURITY ");
411 plog_info("\t\tTX offload capa = 0x%lx = ", port_cfg->dev_info.tx_offload_capa);
412 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)
413 plog_info("VLAN INSERT | ");
414 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)
415 plog_info("IPV4 CKSUM | ");
416 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)
417 plog_info("UDP CKSUM | ");
418 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)
419 plog_info("TCP CKSUM | ");
420 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM)
421 plog_info("SCTP CKSUM | ");
422 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO)
423 plog_info("TCP TS0 | ");
424 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO)
425 plog_info("UDP TSO | ");
426 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)
427 plog_info("OUTER IPV4 CKSUM | ");
428 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT)
429 plog_info("QINQ INSERT | ");
430 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO)
431 plog_info("VLAN TNL TSO | ");
432 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO)
433 plog_info("GRE TNL TSO | ");
434 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO)
435 plog_info("IPIP TNL TSO | ");
436 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO)
437 plog_info("GENEVE TNL TSO | ");
438 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MACSEC_INSERT)
439 plog_info("MACSEC INSERT | ");
440 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MT_LOCKFREE)
441 plog_info("MT LOCKFREE | ");
442 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MULTI_SEGS)
443 plog_info("MULTI SEG | ");
444 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SECURITY)
445 plog_info("SECURITY | ");
446 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO)
447 plog_info("UDP TNL TSO | ");
448 if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO)
449 plog_info("IP TNL TSO | ");
452 plog_info("\t\trx_queue_offload_capa = 0x%lx\n", port_cfg->dev_info.rx_queue_offload_capa);
453 plog_info("\t\ttx_queue_offload_capa = 0x%lx\n", port_cfg->dev_info.tx_queue_offload_capa);
454 plog_info("\t\tflow_type_rss_offloads = 0x%lx\n", port_cfg->dev_info.flow_type_rss_offloads);
455 plog_info("\t\tdefault RX port conf: burst_size = %d, ring_size = %d, nb_queues = %d\n", port_cfg->dev_info.default_rxportconf.burst_size, port_cfg->dev_info.default_rxportconf.ring_size, port_cfg->dev_info.default_rxportconf.nb_queues);
456 plog_info("\t\tdefault TX port conf: burst_size = %d, ring_size = %d, nb_queues = %d\n", port_cfg->dev_info.default_txportconf.burst_size, port_cfg->dev_info.default_txportconf.ring_size, port_cfg->dev_info.default_txportconf.nb_queues);
459 // rxmode such as hw src strip
460 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
461 CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_CRC_STRIP);
462 CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_JUMBO_FRAME);
464 if (port_cfg->requested_rx_offload & DEV_RX_OFFLOAD_CRC_STRIP) {
465 port_cfg->port_conf.rxmode.hw_strip_crc = 1;
467 if (port_cfg->requested_rx_offload & DEV_RX_OFFLOAD_JUMBO_FRAME) {
468 port_cfg->port_conf.rxmode.jumbo_frame = 1;
472 // IPV4, UDP, SCTP Checksums
473 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
474 CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_IPV4_CKSUM);
475 CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_UDP_CKSUM);
477 if ((port_cfg->dev_info.tx_offload_capa & (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM)) == 0) {
478 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOOFFLOADS;
479 plog_info("\t\tDisabling TX offloads as pmd reports that it does not support them)\n");
481 if (!strcmp(port_cfg->short_name, "vmxnet3")) {
482 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMSCTP;
483 plog_info("\t\tDisabling SCTP offload on port %d as vmxnet3 does not support them\n", port_id);
487 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
488 CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_MULTI_SEGS);
489 //if (port_cfg->requested_tx_offload & DEV_TX_OFFLOAD_MULTI_SEGS) {
490 //if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MULTI_SEGS) {
491 //port_cfg->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
492 //plog_info("\t\tMULTI SEGS TX offloads enabled on port)\n");
493 //} else if (port_cfg->dev_info.tx_queue_offload_capa & DEV_TX_OFFLOAD_MULTI_SEGS) {
494 //port_cfg->tx_conf.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
495 //plog_info("\t\tMULTI SEGS TX offloads enabled on queue)\n");
497 //port_cfg->requested_tx_offload &= ~DEV_TX_OFFLOAD_MULTI_SEGS;
498 //plog_info("\t\tMULTI SEGS TX offloads disabled) as neither port or queue supports it\n");
501 //plog_info("\t\tMULTI SEGS TX offloads disabled)\n");
503 if (!strcmp(port_cfg->short_name, "vmxnet3")) {
504 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
505 plog_info("\t\tDisabling TX multsegs on port %d as vmxnet3 does not support them\n", port_id);
506 } else if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOMULTSEGS)
507 plog_info("\t\tDisabling TX multsegs on port %d\n", port_id);
509 plog_info("\t\tEnabling TX multsegs on port %d\n", port_id);
511 if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS)
512 plog_info("\t\tEnabling No TX offloads on port %d\n", port_id);
514 plog_info("\t\tTX offloads enabled on port %d\n", port_id);
518 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
519 CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_MBUF_FAST_FREE);
521 if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOREFCOUNT)
522 plog_info("\t\tEnabling No refcnt on port %d\n", port_id);
524 plog_info("\t\tRefcnt enabled on port %d\n", port_id);
527 plog_info("\t\tConfiguring port %u... with %u RX queues and %u TX queues\n",
528 port_id, port_cfg->n_rxq, port_cfg->n_txq);
530 PROX_PANIC(port_cfg->n_rxq > port_cfg->max_rxq, "\t\t\tToo many RX queues (configuring %u, max is %u)\n", port_cfg->n_rxq, port_cfg->max_rxq);
531 PROX_PANIC(port_cfg->n_txq > port_cfg->max_txq, "\t\t\tToo many TX queues (configuring %u, max is %u)\n", port_cfg->n_txq, port_cfg->max_txq);
533 if (!strcmp(port_cfg->short_name, "ixgbe_vf") ||
534 !strcmp(port_cfg->short_name, "virtio") ||
535 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
536 !strcmp(port_cfg->short_name, "i40e") ||
538 !strcmp(port_cfg->short_name, "i40e_vf") ||
539 !strcmp(port_cfg->short_name, "avp") || /* Wind River */
540 !strcmp(port_cfg->driver_name, "") || /* NULL device */
541 !strcmp(port_cfg->short_name, "vmxnet3")) {
542 port_cfg->port_conf.intr_conf.lsc = 0;
543 plog_info("\t\tDisabling link state interrupt for vmxnet3/VF/virtio (unsupported)\n");
546 if (port_cfg->lsc_set_explicitely) {
547 port_cfg->port_conf.intr_conf.lsc = port_cfg->lsc_val;
548 plog_info("\t\tOverriding link state interrupt configuration to '%s'\n", port_cfg->lsc_val? "enabled" : "disabled");
550 if (!strcmp(port_cfg->short_name, "vmxnet3")) {
551 if (port_cfg->n_txd < 512) {
552 // Vmxnet3 driver requires minimum 512 tx descriptors
553 plog_info("\t\tNumber of TX descriptors is set to 512 (minimum required for vmxnet3\n");
554 port_cfg->n_txd = 512;
558 ret = rte_eth_dev_configure(port_id, port_cfg->n_rxq,
559 port_cfg->n_txq, &port_cfg->port_conf);
560 PROX_PANIC(ret < 0, "\t\t\trte_eth_dev_configure() failed on port %u: %s (%d)\n", port_id, strerror(-ret), ret);
562 if (port_cfg->port_conf.intr_conf.lsc) {
563 rte_eth_dev_callback_register(port_id, RTE_ETH_EVENT_INTR_LSC, lsc_cb, NULL);
566 plog_info("\t\tMAC address set to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
568 /* initialize TX queues first */
569 for (uint16_t queue_id = 0; queue_id < port_cfg->n_txq; ++queue_id) {
570 plog_info("\t\tSetting up TX queue %u on socket %u with %u desc\n",
571 queue_id, port_cfg->socket, port_cfg->n_txd);
572 ret = rte_eth_tx_queue_setup(port_id, queue_id, port_cfg->n_txd,
573 port_cfg->socket, &port_cfg->tx_conf);
574 PROX_PANIC(ret < 0, "\t\t\trte_eth_tx_queue_setup() failed on port %u: error %d\n", port_id, ret);
577 /* initialize RX queues */
578 for (uint16_t queue_id = 0; queue_id < port_cfg->n_rxq; ++queue_id) {
579 plog_info("\t\tSetting up RX queue %u on port %u on socket %u with %u desc (pool 0x%p)\n",
580 queue_id, port_id, port_cfg->socket,
581 port_cfg->n_rxd, port_cfg->pool[queue_id]);
582 ret = rte_eth_rx_queue_setup(port_id, queue_id,
584 port_cfg->socket, &port_cfg->rx_conf,
585 port_cfg->pool[queue_id]);
586 PROX_PANIC(ret < 0, "\t\t\trte_eth_rx_queue_setup() failed on port %u: error %s (%d)\n", port_id, strerror(-ret), ret);
589 plog_info("\t\tStarting up port %u ...", port_id);
590 ret = rte_eth_dev_start(port_id);
592 PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_start() failed on port %u: error %d\n", port_id, ret);
593 plog_info(" done: ");
595 /* Getting link status can be done without waiting if Link
596 State Interrupt is enabled since in that case, if the link
597 is recognized as being down, an interrupt will notify that
599 if (port_cfg->port_conf.intr_conf.lsc)
600 rte_eth_link_get_nowait(port_id, &link);
602 rte_eth_link_get(port_id, &link);
604 port_cfg->link_up = link.link_status;
605 port_cfg->link_speed = link.link_speed;
606 if (link.link_status) {
607 plog_info("Link Up - speed %'u Mbps - %s\n",
609 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
610 "full-duplex" : "half-duplex");
613 plog_info("Link Down\n");
616 if (port_cfg->promiscuous) {
617 rte_eth_promiscuous_enable(port_id);
618 plog_info("\t\tport %u in promiscuous mode\n", port_id);
621 if (strcmp(port_cfg->short_name, "ixgbe_vf") &&
622 strcmp(port_cfg->short_name, "i40e") &&
623 strcmp(port_cfg->short_name, "i40e_vf") &&
624 strcmp(port_cfg->short_name, "vmxnet3")) {
625 for (uint8_t i = 0; i < 16; ++i) {
626 ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, i, i);
628 plog_info("\t\trte_eth_dev_set_rx_queue_stats_mapping() failed: error %d\n", ret);
630 ret = rte_eth_dev_set_tx_queue_stats_mapping(port_id, i, i);
632 plog_info("\t\trte_eth_dev_set_tx_queue_stats_mapping() failed: error %d\n", ret);
638 void init_port_all(void)
640 uint8_t max_port_idx = prox_last_port_active() + 1;
642 for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
643 if (!prox_port_cfg[portid].active) {
646 init_port(&prox_port_cfg[portid]);
650 void close_ports_atexit(void)
652 uint8_t max_port_idx = prox_last_port_active() + 1;
654 for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
655 if (!prox_port_cfg[portid].active) {
658 rte_eth_dev_close(portid);
662 void init_port_addr(void)
664 struct prox_port_cfg *port_cfg;
666 for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
667 if (!prox_port_cfg[port_id].active) {
670 port_cfg = &prox_port_cfg[port_id];
672 switch (port_cfg->type) {
673 case PROX_PORT_MAC_HW:
674 rte_eth_macaddr_get(port_id, &port_cfg->eth_addr);
676 case PROX_PORT_MAC_RAND:
677 eth_random_addr(port_cfg->eth_addr.addr_bytes);
679 case PROX_PORT_MAC_SET:
685 int port_is_active(uint8_t port_id)
687 if (port_id > PROX_MAX_PORTS) {
688 plog_info("requested port is higher than highest supported port ID (%u)\n", PROX_MAX_PORTS);
692 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
693 if (!port_cfg->active) {
694 plog_info("Port %u is not active\n", port_id);