Fix compilation issues on old DPDK
[samplevnf.git] / VNFs / DPPD-PROX / prox_port_cfg.c
1 /*
2 // Copyright (c) 2010-2020 Intel Corporation
3 //
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
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 */
16
17 #include <string.h>
18 #include <stdio.h>
19 #include <rte_version.h>
20 #include <rte_eth_ring.h>
21 #include <rte_mbuf.h>
22 #if (RTE_VERSION >= RTE_VERSION_NUM(17,11,0,0))
23 #include <rte_bus_vdev.h>
24 #else
25 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,2))
26 #include <rte_dev.h>
27 #else
28 #if (RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0))
29 #include <rte_eth_null.h>
30 #endif
31 #endif
32 #endif
33
34 #include <sys/ioctl.h>
35 #include <net/if.h>
36
37 #include "prox_port_cfg.h"
38 #include "prox_globals.h"
39 #include "log.h"
40 #include "quit.h"
41 #include "defaults.h"
42 #include "toeplitz.h"
43 #include "defines.h"
44 #include "prox_cksum.h"
45 #include "stats_irq.h"
46 #include "prox_compat.h"
47 #include "rte_ethdev.h"
48 #include "lconf.h"
49
50 struct prox_port_cfg prox_port_cfg[PROX_MAX_PORTS];
51
52 rte_atomic32_t lsc;
53
54 int prox_nb_active_ports(void)
55 {
56         int ret = 0;
57         for (uint32_t i = 0; i < PROX_MAX_PORTS; ++i) {
58                 ret += prox_port_cfg[i].active;
59         }
60         return ret;
61 }
62
63 int prox_last_port_active(void)
64 {
65         int ret = -1;
66         for (uint32_t i = 0; i < PROX_MAX_PORTS; ++i) {
67                 if (prox_port_cfg[i].active) {
68                         ret = i;
69                 }
70         }
71         return ret;
72 }
73
74 #if RTE_VERSION >= RTE_VERSION_NUM(17,11,0,0)
75 static int lsc_cb(__attribute__((unused)) uint16_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
76         __attribute__((unused)) void *ret_param)
77 #else
78 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
79 static int lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
80         __attribute__((unused)) void *ret_param)
81 #else
82 static void lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param)
83 #endif
84 #endif
85 {
86         if (RTE_ETH_EVENT_INTR_LSC != type) {
87 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
88                 return -1;
89 #else
90                 return;
91 #endif
92         }
93
94         rte_atomic32_inc(&lsc);
95
96 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
97         return 0;
98 #endif
99 }
100
101 struct prox_pktmbuf_reinit_args {
102         struct rte_mempool *mp;
103         struct lcore_cfg   *lconf;
104 };
105
106 /* standard mbuf initialization procedure */
107 void prox_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigned i)
108 {
109         struct rte_mbuf *mbuf = _m;
110
111 #if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
112         mbuf->tx_offload = CALC_TX_OL(sizeof(prox_rte_ether_hdr), sizeof(prox_rte_ipv4_hdr));
113 #else
114         mbuf->pkt.vlan_macip.f.l2_len = sizeof(prox_rte_ether_hdr);
115         mbuf->pkt.vlan_macip.f.l3_len = sizeof(prox_rte_ipv4_hdr);
116 #endif
117
118         rte_pktmbuf_init(mp, opaque_arg, mbuf, i);
119 }
120
121 void prox_pktmbuf_reinit(void *arg, void *start, __attribute__((unused)) void *end, uint32_t idx)
122 {
123         struct prox_pktmbuf_reinit_args *init_args = arg;
124         struct rte_mbuf *m;
125         char* obj = start;
126
127         obj += init_args->mp->header_size;
128         m = (struct rte_mbuf*)obj;
129
130         prox_pktmbuf_init(init_args->mp, init_args->lconf, obj, idx);
131 }
132
133 #define CONFIGURE_TX_OFFLOAD(flag)                                           \
134         if (port_cfg->requested_tx_offload & flag)                              {\
135                 if (port_cfg->disabled_tx_offload & flag)                       {\
136                         plog_info("\t\t%s disabled by configuration\n", #flag);\
137                         port_cfg->requested_tx_offload &= ~flag;\
138                 } else if (port_cfg->dev_info.tx_offload_capa & flag) {\
139                         port_cfg->port_conf.txmode.offloads |= flag;\
140                         plog_info("\t\t%s enabled on port\n", #flag);\
141                 } else if (port_cfg->dev_info.tx_queue_offload_capa & flag) {\
142                         port_cfg->tx_conf.offloads |= flag;\
143                         plog_info("\t\t%s enabled on queue\n", #flag);\
144                 } else {\
145                         port_cfg->requested_tx_offload &= ~flag;\
146                         plog_info("\t\t%s disabled as neither port or queue supports it\n", #flag);\
147                 }\
148         } else {\
149                 plog_info("\t\t%s disabled\n", #flag);\
150         }\
151
152 #define CONFIGURE_RX_OFFLOAD(flag)                                           \
153         if (port_cfg->requested_rx_offload & flag)                              {\
154                 if (port_cfg->dev_info.rx_offload_capa & flag) {\
155                         port_cfg->port_conf.rxmode.offloads |= flag;\
156                         plog_info("\t\t%s enabled on port\n", #flag);\
157                 } else if (port_cfg->dev_info.rx_queue_offload_capa & flag) {\
158                         port_cfg->rx_conf.offloads |= flag;\
159                         plog_info("\t\t%s enabled on queue\n", #flag);\
160                 } else {\
161                         port_cfg->requested_rx_offload &= ~flag;\
162                         plog_info("\t\t%s disabled as neither port or queue supports it\n", #flag);\
163                 }\
164         } else {\
165                 plog_info("\t\t%s disabled\n", #flag);\
166         }\
167
168 static inline uint32_t get_netmask(uint8_t prefix)
169 {
170         if (prefix == 0)
171                 return(~((uint32_t) -1));
172         else
173                 return rte_cpu_to_be_32(~((1 << (32 - prefix)) - 1));
174 }
175
176 static void set_ip_address(char *devname, uint32_t *ip, uint8_t prefix)
177 {
178         struct ifreq ifreq;
179         struct sockaddr_in in_addr;
180         int fd, rc;
181         uint32_t netmask = get_netmask(prefix);
182         plog_info("Setting netmask to %x\n", netmask);
183
184         fd = socket(AF_INET, SOCK_DGRAM, 0);
185
186         memset(&ifreq, 0, sizeof(struct ifreq));
187         memset(&in_addr, 0, sizeof(struct sockaddr_in));
188
189         in_addr.sin_family = AF_INET;
190         in_addr.sin_addr = *(struct in_addr *)ip;
191
192         strncpy(ifreq.ifr_name, devname, IFNAMSIZ);
193         ifreq.ifr_addr = *(struct sockaddr *)&in_addr;
194         rc = ioctl(fd, SIOCSIFADDR, &ifreq);
195         PROX_PANIC(rc < 0, "Failed to set IP address %x on device %s: error = %d (%s)\n", *ip, devname, errno, strerror(errno));
196
197         in_addr.sin_addr = *(struct in_addr *)&netmask;
198         ifreq.ifr_netmask = *(struct sockaddr *)&in_addr;
199         rc = ioctl(fd, SIOCSIFNETMASK, &ifreq);
200         PROX_PANIC(rc < 0, "Failed to set netmask %x (prefix %d) on device %s: error = %d (%s)\n", netmask, prefix, devname, errno, strerror(errno));
201         close(fd);
202 }
203
204 /* initialize rte devices and check the number of available ports */
205 void init_rte_dev(int use_dummy_devices)
206 {
207         uint8_t nb_ports, port_id_max;
208         int port_id_last, rc = 0;
209         struct rte_eth_dev_info dev_info;
210         const struct rte_pci_device *pci_dev;
211
212         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
213                 if (!prox_port_cfg[port_id].active) {
214                         continue;
215                 }
216                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
217                 if (port_cfg->vdev[0]) {
218                         char name[MAX_NAME_SIZE], tap[MAX_NAME_SIZE];
219                         snprintf(tap, MAX_NAME_SIZE, "net_tap%d", port_id);
220 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
221                         snprintf(name, MAX_NAME_SIZE, "iface=%s", port_cfg->vdev);
222                         rc = rte_vdev_init(tap, name);
223 #else
224                         PROX_PANIC(1, "vdev not supported in DPDK < 17.05\n");
225 #endif
226                         PROX_PANIC(rc != 0, "Unable to create device %s %s\n", "net tap", port_cfg->vdev);
227                         int vdev_port_id = prox_rte_eth_dev_count_avail() - 1;
228                         PROX_PANIC(vdev_port_id >= PROX_MAX_PORTS, "Too many port defined %d >= %d\n", vdev_port_id, PROX_MAX_PORTS);
229                         plog_info("\tCreating device %s, port %d\n", port_cfg->vdev, vdev_port_id);
230                         prox_port_cfg[vdev_port_id].is_vdev = 1;
231                         prox_port_cfg[vdev_port_id].active = 1;
232                         prox_port_cfg[vdev_port_id].dpdk_mapping = port_id;
233                         prox_port_cfg[vdev_port_id].n_txq = 1;
234
235                         if (prox_port_cfg[port_id].vlan_tag) {
236                                 char command[1024];
237                                 snprintf(prox_port_cfg[vdev_port_id].name, MAX_NAME_SIZE, "%s_%d", port_cfg->vdev, prox_port_cfg[port_id].vlan_tag);
238                                 sprintf(command, "ip link add link %s name %s type vlan id %d", port_cfg->vdev, prox_port_cfg[vdev_port_id].name, prox_port_cfg[port_id].vlan_tag);
239                                 system(command);
240                                 plog_info("Running %s\n", command);
241                                 plog_info("Using vlan tag %d - added device %s\n", prox_port_cfg[port_id].vlan_tag, prox_port_cfg[vdev_port_id].name);
242                         } else
243                                 strncpy(prox_port_cfg[vdev_port_id].name, port_cfg->vdev, MAX_NAME_SIZE);
244
245                         prox_port_cfg[port_id].dpdk_mapping = vdev_port_id;
246                         prox_port_cfg[vdev_port_id].ip = rte_be_to_cpu_32(prox_port_cfg[port_id].ip);
247                         prox_port_cfg[vdev_port_id].prefix = prox_port_cfg[port_id].prefix;
248                         prox_port_cfg[vdev_port_id].type = prox_port_cfg[port_id].type;
249                         if (prox_port_cfg[vdev_port_id].type == PROX_PORT_MAC_HW) {
250                                 // If DPDK port MAC set to HW, then make sure the vdev has the same MAC as DPDK port
251                                 prox_port_cfg[vdev_port_id].type = PROX_PORT_MAC_SET;
252                                 rte_eth_macaddr_get(port_id, &prox_port_cfg[vdev_port_id].eth_addr);
253                                 plog_info("\tDPDK port %d MAC address pre-configured to MAC from port %d: "MAC_BYTES_FMT"\n",
254                                         vdev_port_id, port_id, MAC_BYTES(prox_port_cfg[vdev_port_id].eth_addr.addr_bytes));
255                         } else
256                                 memcpy(&prox_port_cfg[vdev_port_id].eth_addr, &prox_port_cfg[port_id].eth_addr, sizeof(prox_port_cfg[port_id].eth_addr));
257                 }
258         }
259         nb_ports = prox_rte_eth_dev_count_avail();
260         /* get available ports configuration */
261         PROX_PANIC(use_dummy_devices && nb_ports, "Can't use dummy devices while there are also real ports\n");
262
263         if (use_dummy_devices) {
264 #if (RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0))
265                 nb_ports = prox_last_port_active() + 1;
266                 plog_info("Creating %u dummy devices\n", nb_ports);
267
268                 char port_name[32] = "0dummy_dev";
269                 for (uint32_t i = 0; i < nb_ports; ++i) {
270 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
271                         rte_vdev_init(port_name, "size=64,copy=0");
272 #else
273                         eth_dev_null_create(port_name, 0, PROX_RTE_ETHER_MIN_LEN, 0);
274 #endif
275                         port_name[0]++;
276                 }
277 #else
278         PROX_PANIC(use_dummy_devices, "Can't use dummy devices\n");
279 #endif
280         }
281         else if (prox_last_port_active() != -1) {
282                 PROX_PANIC(nb_ports == 0, "\tError: DPDK could not find any port\n");
283                 plog_info("\tDPDK has found %u ports\n", nb_ports);
284         }
285
286         if (nb_ports > PROX_MAX_PORTS) {
287                 plog_warn("\tWarning: I can deal with at most %u ports."
288                         " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
289
290                 nb_ports = PROX_MAX_PORTS;
291         }
292
293 #if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
294         port_id_max = -1;
295         uint16_t id;
296         RTE_ETH_FOREACH_DEV(id) {
297                 char name[256];
298                 rte_eth_dev_get_name_by_port(id, name);
299                 plog_info("\tFound DPDK port id %u %s\n", id, name);
300                 if (id >= PROX_MAX_PORTS) {
301                         plog_warn("\tWarning: I can deal with at most %u ports."
302                                  " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
303                 } else {
304                         prox_port_cfg[id].available = 1;
305                         if (id > port_id_max)
306                                 port_id_max = id;
307                 }
308         }
309 #else
310         port_id_max = nb_ports - 1;
311 #endif
312
313         port_id_last = prox_last_port_active();
314         PROX_PANIC(port_id_last > port_id_max,
315                    "\tError: invalid port(s) specified, last port index active: %d (max index is %d)\n",
316                    port_id_last, port_id_max);
317
318         /* Assign ports to PROX interfaces & Read max RX/TX queues per port */
319 #if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
320         for (uint8_t port_id = 0; port_id <= port_id_last; ++port_id) {
321 #else
322         for (uint8_t port_id = 0; port_id <= nb_ports; ++port_id) {
323 #endif
324                 /* skip ports that are not enabled */
325                 if (!prox_port_cfg[port_id].active) {
326                         continue;
327 #if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
328                 } else if (prox_port_cfg[port_id].available == 0) {
329                         PROX_PANIC(1, "port %u enabled but not available\n", port_id);
330 #endif
331                 }
332                 plog_info("\tGetting info for rte dev %u\n", port_id);
333                 rte_eth_dev_info_get(port_id, &dev_info);
334                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
335                 port_cfg->socket = -1;
336
337                 memcpy(&port_cfg->dev_info, &dev_info, sizeof(struct rte_eth_dev_info));
338                 port_cfg->max_txq = dev_info.max_tx_queues;
339                 port_cfg->max_rxq = dev_info.max_rx_queues;
340                 port_cfg->max_rx_pkt_len = dev_info.max_rx_pktlen;
341                 port_cfg->min_rx_bufsize = dev_info.min_rx_bufsize;
342                 port_cfg->min_tx_desc = dev_info.tx_desc_lim.nb_min;
343                 port_cfg->max_tx_desc = dev_info.tx_desc_lim.nb_max;
344                 port_cfg->min_rx_desc = dev_info.rx_desc_lim.nb_min;
345                 port_cfg->max_rx_desc = dev_info.rx_desc_lim.nb_max;
346
347                 prox_strncpy(port_cfg->driver_name, dev_info.driver_name, sizeof(port_cfg->driver_name));
348                 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);
349                 plog_info("\tPort %u : %d<=nb_tx_desc<=%d %d<=nb_rx_desc<=%d\n", port_id, port_cfg->min_tx_desc, port_cfg->max_tx_desc, port_cfg->min_rx_desc, port_cfg->max_rx_desc);
350
351                 if (strncmp(port_cfg->driver_name, "rte_", 4) == 0) {
352                         prox_strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
353                 } else if (strncmp(port_cfg->driver_name, "net_", 4) == 0) {
354                         prox_strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
355                 } else {
356                         prox_strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name, sizeof(port_cfg->short_name));
357                 }
358                 char *ptr;
359                 if ((ptr = strstr(port_cfg->short_name, "_pmd")) != NULL) {
360                         *ptr = '\x0';
361                 }
362
363 #if RTE_VERSION < RTE_VERSION_NUM(18,5,0,0)
364                 pci_dev = dev_info.pci_dev;
365 #else
366                 if (!dev_info.device)
367                         continue;
368                 pci_dev = RTE_DEV_TO_PCI(dev_info.device);
369 #endif
370                 if (!pci_dev)
371                         continue;
372
373                 snprintf(port_cfg->pci_addr, sizeof(port_cfg->pci_addr),
374                          "%04x:%02x:%02x.%1x", pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function);
375                 /* Try to find the device's numa node */
376                 char buf[1024];
377                 snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/numa_node", port_cfg->pci_addr);
378                 FILE* numa_node_fd = fopen(buf, "r");
379                 if (numa_node_fd) {
380                         if (fgets(buf, sizeof(buf), numa_node_fd) == NULL) {
381                                 plog_warn("Failed to read numa_node for device %s\n", port_cfg->pci_addr);
382                         }
383                         port_cfg->socket = strtol(buf, 0, 0);
384                         if (port_cfg->socket == -1) {
385                                 plog_warn("System did not report numa_node for device %s\n", port_cfg->pci_addr);
386                         }
387                         fclose(numa_node_fd);
388                 }
389
390                 // In DPDK 18.08 vmxnet3 reports it supports IPV4 checksum, but packets does not go through when IPv4 cksum is enabled
391                 if ((!strcmp(port_cfg->short_name, "vmxnet3")) && (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {
392                         plog_info("\t\tDisabling IPV4 cksum on vmxnet3\n");
393                         port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_IPV4_CKSUM;
394                 }
395                 if ((!strcmp(port_cfg->short_name, "vmxnet3")) && (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) {
396                         plog_info("\t\tDisabling UDP cksum on vmxnet3\n");
397                         port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_UDP_CKSUM;
398                 }
399                 // Some OVS versions reports that they support UDP offload and no IPv4 offload, but fails when UDP offload is enabled
400                 if ((!strcmp(port_cfg->short_name, "virtio")) &&
401                         ((port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0) &&
402                         (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) {
403                         plog_info("\t\tDisabling UDP cksum on virtio\n");
404                         port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_UDP_CKSUM;
405                 }
406         }
407 }
408
409 /* Create rte ring-backed devices */
410 uint8_t init_rte_ring_dev(void)
411 {
412         uint8_t nb_ring_dev = 0;
413
414         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
415                 /* skip ports that are not enabled */
416                 if (!prox_port_cfg[port_id].active) {
417                         continue;
418                 }
419                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
420                 if (port_cfg->rx_ring[0] != '\0') {
421                         plog_info("\tRing-backed port %u: rx='%s' tx='%s'\n", port_id, port_cfg->rx_ring, port_cfg->tx_ring);
422
423                         struct rte_ring* rx_ring = rte_ring_lookup(port_cfg->rx_ring);
424                         PROX_PANIC(rx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->rx_ring, port_id);
425                         struct rte_ring* tx_ring = rte_ring_lookup(port_cfg->tx_ring);
426                         PROX_PANIC(tx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->tx_ring, port_id);
427
428                         int ret = rte_eth_from_rings(port_cfg->name, &rx_ring, 1, &tx_ring, 1, rte_socket_id());
429                         PROX_PANIC(ret != 0, "Failed to create eth_dev from rings for port %d\n", port_id);
430
431                         port_cfg->port_conf.intr_conf.lsc = 0; /* Link state interrupt not supported for ring-backed ports */
432
433                         nb_ring_dev++;
434                 }
435         }
436
437         return nb_ring_dev;
438 }
439
440 static void print_port_capa(struct prox_port_cfg *port_cfg)
441 {
442         uint8_t port_id;
443
444         port_id = port_cfg - prox_port_cfg;
445         plog_info("\t*** Initializing port %u ***\n", port_id);
446         plog_info("\t\tPort name is set to %s\n", port_cfg->name);
447         plog_info("\t\tPort max RX/TX queue is %u/%u\n", port_cfg->max_rxq, port_cfg->max_txq);
448         plog_info("\t\tPort driver is %s\n", port_cfg->driver_name);
449 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0)
450         plog_info("\t\tSupported speed mask = 0x%x\n", port_cfg->dev_info.speed_capa);
451 #endif
452         if (port_cfg->max_link_speed != UINT32_MAX) {
453                 plog_info("\t\tHighest link speed capa = %d Mbps\n", port_cfg->max_link_speed);
454         }
455
456 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
457         plog_info("\t\tRX offload capa = 0x%lx = ", port_cfg->dev_info.rx_offload_capa);
458         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP)
459                 plog_info("VLAN STRIP | ");
460         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM)
461                 plog_info("IPV4 CKSUM | ");
462         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM)
463                 plog_info("UDP CKSUM | ");
464         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)
465                 plog_info("TCP CKSUM | ");
466         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO)
467                 plog_info("TCP LRO | ");
468         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP)
469                 plog_info("QINQ STRIP | ");
470         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
471                 plog_info("OUTER_IPV4_CKSUM | ");
472         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_MACSEC_STRIP)
473                 plog_info("MACSEC STRIP | ");
474         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_HEADER_SPLIT)
475                 plog_info("HEADER SPLIT | ");
476         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_FILTER)
477                 plog_info("VLAN FILTER | ");
478         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_EXTEND)
479                 plog_info("VLAN EXTEND | ");
480         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME)
481                 plog_info("JUMBO FRAME | ");
482 #if defined(DEV_RX_OFFLOAD_CRC_STRIP)
483         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_CRC_STRIP)
484                 plog_info("CRC STRIP | ");
485 #endif
486 #if defined(DEV_RX_OFFLOAD_KEEP_CRC)
487         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC)
488                 plog_info("KEEP CRC | ");
489 #endif
490         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCATTER)
491                 plog_info("SCATTER | ");
492         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP)
493                 plog_info("TIMESTAMP | ");
494         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY)
495                 plog_info("SECURITY ");
496         plog_info("\n");
497
498         plog_info("\t\tTX offload capa = 0x%lx = ", port_cfg->dev_info.tx_offload_capa);
499         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)
500                 plog_info("VLAN INSERT | ");
501         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)
502                 plog_info("IPV4 CKSUM | ");
503         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)
504                 plog_info("UDP CKSUM | ");
505         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)
506                 plog_info("TCP CKSUM | ");
507         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM)
508                 plog_info("SCTP CKSUM | ");
509         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO)
510                 plog_info("TCP TS0 | ");
511         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO)
512                 plog_info("UDP TSO | ");
513         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)
514                 plog_info("OUTER IPV4 CKSUM | ");
515         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT)
516                 plog_info("QINQ INSERT | ");
517         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO)
518                 plog_info("VLAN TNL TSO | ");
519         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO)
520                 plog_info("GRE TNL TSO | ");
521         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO)
522                 plog_info("IPIP TNL TSO | ");
523         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO)
524                 plog_info("GENEVE TNL TSO | ");
525         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MACSEC_INSERT)
526                 plog_info("MACSEC INSERT | ");
527         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MT_LOCKFREE)
528                 plog_info("MT LOCKFREE | ");
529         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MULTI_SEGS)
530                 plog_info("MULTI SEG | ");
531         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SECURITY)
532                 plog_info("SECURITY | ");
533         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO)
534                 plog_info("UDP TNL TSO | ");
535         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO)
536                 plog_info("IP TNL TSO | ");
537         plog_info("\n");
538
539         plog_info("\t\trx_queue_offload_capa = 0x%lx\n", port_cfg->dev_info.rx_queue_offload_capa);
540         plog_info("\t\ttx_queue_offload_capa = 0x%lx\n", port_cfg->dev_info.tx_queue_offload_capa);
541         plog_info("\t\tflow_type_rss_offloads = 0x%lx\n", port_cfg->dev_info.flow_type_rss_offloads);
542         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);
543         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);
544 #endif
545 }
546
547 static void get_max_link_speed(struct prox_port_cfg *port_cfg)
548 {
549         port_cfg->max_link_speed = UINT32_MAX;
550
551 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0)
552         // virtio and vmxnet3 reports fake max_link_speed
553         if (strcmp(port_cfg->short_name, "vmxnet3") && strcmp(port_cfg->short_name, "virtio")) {
554                 // Get link_speed from highest capability from the port
555                 // This will be used by gen and lat for extrapolation purposes
556                 // The negotiated link_speed (as reported by rte_eth_link_get
557                 // or rte_eth_link_get_nowait) might be reported too late
558                 // and might result in wrong exrapolation, and hence should not be used
559                 // for extrapolation purposes
560                 if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_100G)
561                         port_cfg->max_link_speed = ETH_SPEED_NUM_100G;
562                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_56G)
563                         port_cfg->max_link_speed = ETH_SPEED_NUM_56G;
564                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_50G)
565                         port_cfg->max_link_speed = ETH_SPEED_NUM_50G;
566                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_40G)
567                         port_cfg->max_link_speed = ETH_SPEED_NUM_40G;
568                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_25G)
569                         port_cfg->max_link_speed = ETH_SPEED_NUM_25G;
570                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_20G)
571                         port_cfg->max_link_speed = ETH_SPEED_NUM_20G;
572                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_10G)
573                         port_cfg->max_link_speed = ETH_SPEED_NUM_10G;
574                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_5G)
575                         port_cfg->max_link_speed = ETH_SPEED_NUM_5G;
576                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_2_5G)
577                         port_cfg->max_link_speed = ETH_SPEED_NUM_2_5G;
578                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_1G)
579                         port_cfg->max_link_speed = ETH_SPEED_NUM_1G;
580                 else if (port_cfg->dev_info.speed_capa & (ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M))
581                         port_cfg->max_link_speed = ETH_SPEED_NUM_100M;
582                 else if (port_cfg->dev_info.speed_capa & (ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M))
583                         port_cfg->max_link_speed = ETH_SPEED_NUM_10M;
584
585         }
586 #endif
587 }
588
589 static void init_port(struct prox_port_cfg *port_cfg)
590 {
591         static char dummy_pool_name[] = "0_dummy";
592         struct rte_eth_link link;
593         uint8_t port_id;
594         int ret;
595
596         get_max_link_speed(port_cfg);
597         print_port_capa(port_cfg);
598         port_id = port_cfg - prox_port_cfg;
599         PROX_PANIC(port_cfg->n_rxq == 0 && port_cfg->n_txq == 0,
600                    "\t\t port %u is enabled but no RX or TX queues have been configured", port_id);
601
602         if (port_cfg->n_rxq == 0) {
603                 /* not receiving on this port */
604                 plog_info("\t\tPort %u had no RX queues, setting to 1\n", port_id);
605                 port_cfg->n_rxq = 1;
606                 uint32_t mbuf_size = TX_MBUF_SIZE;
607                 if (mbuf_size < port_cfg->min_rx_bufsize + RTE_PKTMBUF_HEADROOM + sizeof(struct rte_mbuf))
608                         mbuf_size = port_cfg->min_rx_bufsize + RTE_PKTMBUF_HEADROOM + sizeof(struct rte_mbuf);
609
610                 plog_info("\t\tAllocating dummy memory pool on socket %u with %u elements of size %u\n",
611                           port_cfg->socket, port_cfg->n_rxd, mbuf_size);
612                 port_cfg->pool[0] = rte_mempool_create(dummy_pool_name, port_cfg->n_rxd, mbuf_size,
613                                                        0,
614                                                        sizeof(struct rte_pktmbuf_pool_private),
615                                                        rte_pktmbuf_pool_init, NULL,
616                                                        prox_pktmbuf_init, 0,
617                                                        port_cfg->socket, 0);
618                 PROX_PANIC(port_cfg->pool[0] == NULL, "Failed to allocate dummy memory pool on socket %u with %u elements\n",
619                            port_cfg->socket, port_cfg->n_rxd);
620                 dummy_pool_name[0]++;
621         } else {
622                 // Most pmd should now support setting mtu
623                 if (port_cfg->mtu + PROX_RTE_ETHER_HDR_LEN + PROX_RTE_ETHER_CRC_LEN > port_cfg->max_rx_pkt_len) {
624                         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);
625                         port_cfg->mtu = port_cfg->max_rx_pkt_len;
626                 }
627                 plog_info("\t\tSetting MTU size to %u for port %u ...\n", port_cfg->mtu, port_id);
628                 ret = rte_eth_dev_set_mtu(port_id, port_cfg->mtu);
629                 if (ret)
630                         plog_err("\t\t\trte_eth_dev_set_mtu() failed on port %u: error %d\n", port_id, ret);
631
632                 if (port_cfg->n_txq == 0) {
633                         /* not sending on this port */
634                         plog_info("\t\tPort %u had no TX queues, setting to 1\n", port_id);
635                         port_cfg->n_txq = 1;
636                 }
637         }
638
639         if (port_cfg->n_rxq > 1)  {
640                 // Enable RSS if multiple receive queues
641                 port_cfg->port_conf.rxmode.mq_mode                      |= ETH_MQ_RX_RSS;
642                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key        = toeplitz_init_key;
643                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key_len    = TOEPLITZ_KEY_LEN;
644 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
645                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IP|ETH_RSS_UDP;
646 #else
647                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IPV4|ETH_RSS_NONF_IPV4_UDP;
648 #endif
649         }
650
651         // Make sure that the requested RSS offload is supported by the PMD
652 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
653         port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf &= port_cfg->dev_info.flow_type_rss_offloads;
654 #endif
655         plog_info("\t\t Enabling RSS rss_hf = 0x%lx (requested 0x%llx, supported 0x%lx)\n", port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf, ETH_RSS_IP|ETH_RSS_UDP, port_cfg->dev_info.flow_type_rss_offloads);
656
657         // rxmode such as hw src strip
658 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
659 #if defined (DEV_RX_OFFLOAD_CRC_STRIP)
660         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_CRC_STRIP);
661 #endif
662 #if defined (DEV_RX_OFFLOAD_KEEP_CRC)
663         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_KEEP_CRC);
664 #endif
665         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_JUMBO_FRAME);
666         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_VLAN_STRIP);
667 #else
668         if (port_cfg->requested_rx_offload & DEV_RX_OFFLOAD_CRC_STRIP) {
669                 port_cfg->port_conf.rxmode.hw_strip_crc = 1;
670         }
671         if (port_cfg->requested_rx_offload & DEV_RX_OFFLOAD_JUMBO_FRAME) {
672                 port_cfg->port_conf.rxmode.jumbo_frame = 1;
673         }
674 #endif
675
676         // IPV4, UDP, SCTP Checksums
677 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
678         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_IPV4_CKSUM);
679         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_UDP_CKSUM);
680         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_VLAN_INSERT);
681 #else
682         if ((port_cfg->dev_info.tx_offload_capa & (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM)) == 0) {
683                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOOFFLOADS;
684                 plog_info("\t\tDisabling TX offloads as pmd reports that it does not support them)\n");
685         }
686         if (!strcmp(port_cfg->short_name, "vmxnet3")) {
687                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMSCTP;
688                 plog_info("\t\tDisabling SCTP offload on port %d as vmxnet3 does not support them\n", port_id);
689         }
690 #endif
691         // Multi Segments
692 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
693         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_MULTI_SEGS);
694 #else
695         if (!strcmp(port_cfg->short_name, "vmxnet3")) {
696                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
697                 plog_info("\t\tDisabling TX multsegs on port %d as vmxnet3 does not support them\n", port_id);
698         } else if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOMULTSEGS)
699                 plog_info("\t\tDisabling TX multsegs on port %d\n", port_id);
700         else
701                 plog_info("\t\tEnabling TX multsegs on port %d\n", port_id);
702
703         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS)
704                 plog_info("\t\tEnabling No TX offloads on port %d\n", port_id);
705         else
706                 plog_info("\t\tTX offloads enabled on port %d\n", port_id);
707 #endif
708
709         // Refcount
710 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
711         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_MBUF_FAST_FREE);
712 #else
713         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOREFCOUNT)
714                 plog_info("\t\tEnabling No refcnt on port %d\n", port_id);
715         else
716                 plog_info("\t\tRefcnt enabled on port %d\n", port_id);
717 #endif
718
719         plog_info("\t\tConfiguring port %u... with %u RX queues and %u TX queues\n",
720                   port_id, port_cfg->n_rxq, port_cfg->n_txq);
721
722         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);
723         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);
724
725         if (!strcmp(port_cfg->short_name, "ixgbe_vf") ||
726             !strcmp(port_cfg->short_name, "virtio") ||
727 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
728             !strcmp(port_cfg->short_name, "i40e") ||
729 #endif
730             !strcmp(port_cfg->short_name, "i40e_vf") ||
731             !strcmp(port_cfg->short_name, "avp") || /* Wind River */
732             !strcmp(port_cfg->driver_name, "") || /* NULL device */
733             !strcmp(port_cfg->short_name, "vmxnet3")) {
734                 port_cfg->port_conf.intr_conf.lsc = 0;
735                 plog_info("\t\tDisabling link state interrupt for vmxnet3/VF/virtio (unsupported)\n");
736         }
737
738         if (port_cfg->lsc_set_explicitely) {
739                 port_cfg->port_conf.intr_conf.lsc = port_cfg->lsc_val;
740                 plog_info("\t\tOverriding link state interrupt configuration to '%s'\n", port_cfg->lsc_val? "enabled" : "disabled");
741         }
742         if (port_cfg->n_txd < port_cfg->min_tx_desc) {
743                 plog_info("\t\tNumber of TX descriptors is set to %d (minimum required for %s\n", port_cfg->min_tx_desc, port_cfg->short_name);
744                 port_cfg->n_txd = port_cfg->min_tx_desc;
745         }
746
747         if (port_cfg->n_rxd < port_cfg->min_rx_desc) {
748                 plog_info("\t\tNumber of RX descriptors is set to %d (minimum required for %s\n", port_cfg->min_rx_desc, port_cfg->short_name);
749                 port_cfg->n_rxd = port_cfg->min_rx_desc;
750         }
751
752         if (port_cfg->n_txd > port_cfg->max_tx_desc) {
753                 plog_info("\t\tNumber of TX descriptors is set to %d (maximum required for %s\n", port_cfg->max_tx_desc, port_cfg->short_name);
754                 port_cfg->n_txd = port_cfg->max_tx_desc;
755         }
756
757         if (port_cfg->n_rxd > port_cfg->max_rx_desc) {
758                 plog_info("\t\tNumber of RX descriptors is set to %d (maximum required for %s\n", port_cfg->max_rx_desc, port_cfg->short_name);
759                 port_cfg->n_rxd = port_cfg->max_rx_desc;
760         }
761
762         ret = rte_eth_dev_configure(port_id, port_cfg->n_rxq,
763                                     port_cfg->n_txq, &port_cfg->port_conf);
764         PROX_PANIC(ret < 0, "\t\t\trte_eth_dev_configure() failed on port %u: %s (%d)\n", port_id, strerror(-ret), ret);
765
766         if (port_cfg->port_conf.intr_conf.lsc) {
767                 rte_eth_dev_callback_register(port_id, RTE_ETH_EVENT_INTR_LSC, lsc_cb, NULL);
768         }
769
770         plog_info("\t\tMAC address set to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
771
772         /* initialize TX queues first */
773         for (uint16_t queue_id = 0; queue_id < port_cfg->n_txq; ++queue_id) {
774                 plog_info("\t\tSetting up TX queue %u on socket %u with %u desc\n",
775                           queue_id, port_cfg->socket, port_cfg->n_txd);
776                 ret = rte_eth_tx_queue_setup(port_id, queue_id, port_cfg->n_txd,
777                                              port_cfg->socket, &port_cfg->tx_conf);
778                 PROX_PANIC(ret < 0, "\t\t\trte_eth_tx_queue_setup() failed on port %u: error %d\n", port_id, ret);
779         }
780
781         /* initialize RX queues */
782         for (uint16_t queue_id = 0; queue_id < port_cfg->n_rxq; ++queue_id) {
783                 plog_info("\t\tSetting up RX queue %u on port %u on socket %u with %u desc (pool 0x%p)\n",
784                           queue_id, port_id, port_cfg->socket,
785                           port_cfg->n_rxd, port_cfg->pool[queue_id]);
786                 ret = rte_eth_rx_queue_setup(port_id, queue_id,
787                                              port_cfg->n_rxd,
788                                              port_cfg->socket, &port_cfg->rx_conf,
789                                              port_cfg->pool[queue_id]);
790                 PROX_PANIC(ret < 0, "\t\t\trte_eth_rx_queue_setup() failed on port %u: error %s (%d)\n", port_id, strerror(-ret), ret);
791         }
792
793         plog_info("\t\tStarting up port %u ...", port_id);
794         ret = rte_eth_dev_start(port_id);
795
796         PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_start() failed on port %u: error %d\n", port_id, ret);
797         plog_info(" done: ");
798
799         if ((prox_port_cfg[port_id].ip) && (prox_port_cfg[port_id].is_vdev)) {
800                 set_ip_address(prox_port_cfg[port_id].name, &prox_port_cfg[port_id].ip, prox_port_cfg[port_id].prefix);
801         }
802         /* Getting link status can be done without waiting if Link
803            State Interrupt is enabled since in that case, if the link
804            is recognized as being down, an interrupt will notify that
805            it has gone up. */
806         if (port_cfg->port_conf.intr_conf.lsc)
807                 rte_eth_link_get_nowait(port_id, &link);
808         else
809                 rte_eth_link_get(port_id, &link);
810
811         port_cfg->link_up = link.link_status;
812         port_cfg->link_speed = link.link_speed;
813
814         if (link.link_status) {
815                 plog_info("Link Up - speed %'u Mbps - %s\n",
816                           link.link_speed,
817                           (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
818                           "full-duplex" : "half-duplex");
819         }
820         else {
821                 plog_info("Link Down\n");
822         }
823
824         if (port_cfg->promiscuous) {
825                 rte_eth_promiscuous_enable(port_id);
826                 plog_info("\t\tport %u in promiscuous mode\n", port_id);
827         }
828
829         if (strcmp(port_cfg->short_name, "ixgbe_vf") &&
830             strcmp(port_cfg->short_name, "i40e") &&
831             strcmp(port_cfg->short_name, "i40e_vf") &&
832             strcmp(port_cfg->short_name, "vmxnet3")) {
833                 for (uint8_t i = 0; i < port_cfg->n_rxq; ++i) {
834                         ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, i, i);
835                         if (ret) {
836                                 plog_info("\t\trte_eth_dev_set_rx_queue_stats_mapping() failed: error %d\n", ret);
837                         }
838                 }
839                 for (uint8_t i = 0; i < port_cfg->n_txq; ++i) {
840                         ret = rte_eth_dev_set_tx_queue_stats_mapping(port_id, i, i);
841                         if (ret) {
842                                 plog_info("\t\trte_eth_dev_set_tx_queue_stats_mapping() failed: error %d\n", ret);
843                         }
844                 }
845         }
846         if (port_cfg->nb_mc_addr) {
847                 rte_eth_allmulticast_enable(port_id);
848                 if ((ret = rte_eth_dev_set_mc_addr_list(port_id, port_cfg->mc_addr, port_cfg->nb_mc_addr)) != 0) {
849                         plog_err("\t\trte_eth_dev_set_mc_addr_list returns %d on port %u\n", ret, port_id);
850                         port_cfg->nb_mc_addr = 0;
851                         rte_eth_allmulticast_disable(port_id);
852                         plog_info("\t\tport %u NOT in multicast mode as failed to add mcast address\n", port_id);
853                 } else {
854                         plog_info("\t\trte_eth_dev_set_mc_addr_list(%d addr) on port %u\n", port_cfg->nb_mc_addr, port_id);
855                         plog_info("\t\tport %u in multicast mode\n", port_id);
856                 }
857         }
858 }
859
860 void init_port_all(void)
861 {
862         enum rte_proc_type_t proc_type;
863         proc_type = rte_eal_process_type();
864         if (proc_type == RTE_PROC_SECONDARY) {
865                 plog_info("\tSkipping port initialization as secondary process\n");
866                 return;
867         }
868         uint8_t max_port_idx = prox_last_port_active() + 1;
869
870         for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
871                 if (!prox_port_cfg[portid].active) {
872                         continue;
873                 }
874                 init_port(&prox_port_cfg[portid]);
875         }
876 }
877
878 void close_ports_atexit(void)
879 {
880         uint8_t max_port_idx = prox_last_port_active() + 1;
881
882         for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
883                 if (!prox_port_cfg[portid].active) {
884                         continue;
885                 }
886                 plog_info("Closing port %u\n", portid);
887                 rte_eth_dev_close(portid);
888         }
889
890         if (lcore_cfg == NULL)
891                 return;
892
893         struct lcore_cfg *lconf = NULL;
894         struct task_args *targ;
895         while (core_targ_next(&lconf, &targ, 0) == 0) {
896                 if (targ->pool) {
897                         rte_mempool_free(targ->pool);
898                         plog_info("freeing pool %p\n", targ->pool);
899                         targ->pool = NULL;
900                 }
901         }
902 }
903
904 void init_port_addr(void)
905 {
906         struct prox_port_cfg *port_cfg;
907         enum rte_proc_type_t proc_type;
908         int rc;
909
910         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
911                 if (!prox_port_cfg[port_id].active) {
912                         continue;
913                 }
914                 port_cfg = &prox_port_cfg[port_id];
915
916                 switch (port_cfg->type) {
917                 case PROX_PORT_MAC_HW:
918                         rte_eth_macaddr_get(port_id, &port_cfg->eth_addr);
919                         break;
920                 case PROX_PORT_MAC_RAND:
921                         prox_rte_eth_random_addr(port_cfg->eth_addr.addr_bytes);
922                         break;
923                 case PROX_PORT_MAC_SET:
924                         proc_type = rte_eal_process_type();
925                         if (proc_type == RTE_PROC_SECONDARY) {
926                                 plog_warn("\tport %u: unable to change port mac address as secondary process\n", port_id);
927                         } else if ((rc = rte_eth_dev_default_mac_addr_set(port_id, &port_cfg->eth_addr)) != 0)
928                                 plog_warn("\tport %u: failed to set mac address. Error = %d\n", port_id, rc);
929                         else
930                                 plog_info("Setting MAC to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
931                         break;
932                 }
933         }
934 }
935
936 int port_is_active(uint8_t port_id)
937 {
938         if (port_id > PROX_MAX_PORTS) {
939                 plog_info("requested port is higher than highest supported port ID (%u)\n", PROX_MAX_PORTS);
940                 return 0;
941         }
942
943         struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
944         if (!port_cfg->active) {
945                 plog_info("Port %u is not active\n", port_id);
946                 return 0;
947         }
948         return 1;
949 }