859c437223c337fcaa0ea1ae86ef08b2f8b2646b
[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
218                 prox_port_cfg[port_id].n_vlans = 0;
219                 while ((prox_port_cfg[port_id].n_vlans < PROX_MAX_VLAN_TAGS) && (prox_port_cfg[port_id].vlan_tags[prox_port_cfg[port_id].n_vlans])) {
220                         prox_port_cfg[port_id].n_vlans++;
221                 }
222
223                 if (port_cfg->vdev[0]) {
224                         char name[MAX_NAME_SIZE], tap[MAX_NAME_SIZE];
225                         snprintf(tap, MAX_NAME_SIZE, "net_tap%d", port_id);
226 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
227                         snprintf(name, MAX_NAME_SIZE, "iface=%s", port_cfg->vdev);
228                         rc = rte_vdev_init(tap, name);
229 #else
230                         PROX_PANIC(1, "vdev not supported in DPDK < 17.05\n");
231 #endif
232                         PROX_PANIC(rc != 0, "Unable to create device %s %s\n", "net tap", port_cfg->vdev);
233                         int vdev_port_id = prox_rte_eth_dev_count_avail() - 1;
234                         PROX_PANIC(vdev_port_id >= PROX_MAX_PORTS, "Too many port defined %d >= %d\n", vdev_port_id, PROX_MAX_PORTS);
235                         plog_info("\tCreating device %s, port %d\n", port_cfg->vdev, vdev_port_id);
236                         prox_port_cfg[vdev_port_id].is_vdev = 1;
237                         prox_port_cfg[vdev_port_id].active = 1;
238                         prox_port_cfg[vdev_port_id].dpdk_mapping = port_id;
239                         prox_port_cfg[vdev_port_id].n_txq = 1;
240                         prox_port_cfg[vdev_port_id].n_vlans = prox_port_cfg[port_id].n_vlans;
241
242                         for (uint32_t tag_id = 0; tag_id < prox_port_cfg[port_id].n_vlans; tag_id++) {
243                                 prox_port_cfg[vdev_port_id].vlan_tags[tag_id] = prox_port_cfg[port_id].vlan_tags[tag_id];
244                                 char command[1024];
245                                 snprintf(prox_port_cfg[vdev_port_id].names[tag_id], MAX_NAME_SIZE, "%s_%d", port_cfg->vdev, prox_port_cfg[port_id].vlan_tags[tag_id]);
246                                 sprintf(command, "ip link add link %s name %s type vlan id %d", port_cfg->vdev, prox_port_cfg[vdev_port_id].names[tag_id], prox_port_cfg[port_id].vlan_tags[tag_id]);
247                                 system(command);
248                                 plog_info("\tRunning %s\n", command);
249                                 plog_info("\tUsing vlan tag %d - added device %s\n", prox_port_cfg[port_id].vlan_tags[tag_id], prox_port_cfg[vdev_port_id].names[tag_id]);
250                         }
251                         if (prox_port_cfg[port_id].n_vlans == 0) {
252                                 strncpy(prox_port_cfg[vdev_port_id].names[0], port_cfg->vdev, MAX_NAME_SIZE);
253                                 prox_port_cfg[vdev_port_id].n_vlans = 1;
254                                 prox_port_cfg[vdev_port_id].vlan_tags[0] = 0;
255                         }
256
257                         prox_port_cfg[port_id].dpdk_mapping = vdev_port_id;
258                         uint32_t i = 0;
259                         while ((i < PROX_MAX_VLAN_TAGS) && (prox_port_cfg[port_id].ip_addr[i].ip)) {
260                                 prox_port_cfg[vdev_port_id].ip_addr[i].ip = rte_be_to_cpu_32(prox_port_cfg[port_id].ip_addr[i].ip);
261                                 prox_port_cfg[vdev_port_id].ip_addr[i].prefix = prox_port_cfg[port_id].ip_addr[i].prefix;
262                                 i++;
263                         }
264                         prox_port_cfg[vdev_port_id].type = prox_port_cfg[port_id].type;
265                         if (prox_port_cfg[vdev_port_id].type == PROX_PORT_MAC_HW) {
266                                 // If DPDK port MAC set to HW, then make sure the vdev has the same MAC as DPDK port
267                                 prox_port_cfg[vdev_port_id].type = PROX_PORT_MAC_SET;
268                                 rte_eth_macaddr_get(port_id, &prox_port_cfg[vdev_port_id].eth_addr);
269                                 plog_info("\tDPDK port %d MAC address pre-configured to MAC from port %d: "MAC_BYTES_FMT"\n",
270                                         vdev_port_id, port_id, MAC_BYTES(prox_port_cfg[vdev_port_id].eth_addr.addr_bytes));
271                         } else
272                                 memcpy(&prox_port_cfg[vdev_port_id].eth_addr, &prox_port_cfg[port_id].eth_addr, sizeof(prox_port_cfg[port_id].eth_addr));
273                 }
274                 if (prox_port_cfg[port_id].n_vlans == 0) {
275                         prox_port_cfg[port_id].n_vlans = 1;
276                         prox_port_cfg[port_id].vlan_tags[0] = 0;
277                 }
278         }
279         nb_ports = prox_rte_eth_dev_count_avail();
280         /* get available ports configuration */
281         PROX_PANIC(use_dummy_devices && nb_ports, "Can't use dummy devices while there are also real ports\n");
282
283         if (use_dummy_devices) {
284 #if (RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0))
285                 nb_ports = prox_last_port_active() + 1;
286                 plog_info("Creating %u dummy devices\n", nb_ports);
287
288                 char port_name[32] = "0dummy_dev";
289                 for (uint32_t i = 0; i < nb_ports; ++i) {
290 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
291                         rte_vdev_init(port_name, "size=64,copy=0");
292 #else
293                         eth_dev_null_create(port_name, 0, PROX_RTE_ETHER_MIN_LEN, 0);
294 #endif
295                         port_name[0]++;
296                 }
297 #else
298         PROX_PANIC(use_dummy_devices, "Can't use dummy devices\n");
299 #endif
300         }
301         else if (prox_last_port_active() != -1) {
302                 PROX_PANIC(nb_ports == 0, "\tError: DPDK could not find any port\n");
303                 plog_info("\tDPDK has found %u ports\n", nb_ports);
304         }
305
306         if (nb_ports > PROX_MAX_PORTS) {
307                 plog_warn("\tWarning: I can deal with at most %u ports."
308                         " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
309
310                 nb_ports = PROX_MAX_PORTS;
311         }
312
313 #if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
314         port_id_max = -1;
315         uint16_t id;
316         RTE_ETH_FOREACH_DEV(id) {
317                 char name[256];
318                 rte_eth_dev_get_name_by_port(id, name);
319                 plog_info("\tFound DPDK port id %u %s\n", id, name);
320                 if (id >= PROX_MAX_PORTS) {
321                         plog_warn("\tWarning: I can deal with at most %u ports."
322                                  " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
323                 } else {
324                         prox_port_cfg[id].available = 1;
325                         if (id > port_id_max)
326                                 port_id_max = id;
327                 }
328         }
329 #else
330         port_id_max = nb_ports - 1;
331 #endif
332
333         port_id_last = prox_last_port_active();
334         PROX_PANIC(port_id_last > port_id_max,
335                    "\tError: invalid port(s) specified, last port index active: %d (max index is %d)\n",
336                    port_id_last, port_id_max);
337
338         /* Assign ports to PROX interfaces & Read max RX/TX queues per port */
339 #if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
340         for (uint8_t port_id = 0; port_id <= port_id_last; ++port_id) {
341 #else
342         for (uint8_t port_id = 0; port_id <= nb_ports; ++port_id) {
343 #endif
344                 /* skip ports that are not enabled */
345                 if (!prox_port_cfg[port_id].active) {
346                         continue;
347 #if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
348                 } else if (prox_port_cfg[port_id].available == 0) {
349                         PROX_PANIC(1, "port %u enabled but not available\n", port_id);
350 #endif
351                 }
352                 plog_info("\tGetting info for rte dev %u\n", port_id);
353                 rte_eth_dev_info_get(port_id, &dev_info);
354                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
355                 port_cfg->socket = -1;
356
357                 memcpy(&port_cfg->dev_info, &dev_info, sizeof(struct rte_eth_dev_info));
358                 port_cfg->max_txq = dev_info.max_tx_queues;
359                 port_cfg->max_rxq = dev_info.max_rx_queues;
360                 port_cfg->max_rx_pkt_len = dev_info.max_rx_pktlen;
361                 port_cfg->min_rx_bufsize = dev_info.min_rx_bufsize;
362                 port_cfg->min_tx_desc = dev_info.tx_desc_lim.nb_min;
363                 port_cfg->max_tx_desc = dev_info.tx_desc_lim.nb_max;
364                 port_cfg->min_rx_desc = dev_info.rx_desc_lim.nb_min;
365                 port_cfg->max_rx_desc = dev_info.rx_desc_lim.nb_max;
366
367                 prox_strncpy(port_cfg->driver_name, dev_info.driver_name, sizeof(port_cfg->driver_name));
368                 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);
369                 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);
370
371                 if (strncmp(port_cfg->driver_name, "rte_", 4) == 0) {
372                         prox_strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
373                 } else if (strncmp(port_cfg->driver_name, "net_", 4) == 0) {
374                         prox_strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
375                 } else {
376                         prox_strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name, sizeof(port_cfg->short_name));
377                 }
378                 char *ptr;
379                 if ((ptr = strstr(port_cfg->short_name, "_pmd")) != NULL) {
380                         *ptr = '\x0';
381                 }
382
383 #if RTE_VERSION < RTE_VERSION_NUM(18,5,0,0)
384                 pci_dev = dev_info.pci_dev;
385 #else
386                 if (!dev_info.device)
387                         continue;
388                 pci_dev = RTE_DEV_TO_PCI(dev_info.device);
389 #endif
390                 if (!pci_dev)
391                         continue;
392
393                 snprintf(port_cfg->pci_addr, sizeof(port_cfg->pci_addr),
394                          "%04x:%02x:%02x.%1x", pci_dev->addr.domain, pci_dev->addr.bus, pci_dev->addr.devid, pci_dev->addr.function);
395                 /* Try to find the device's numa node */
396                 char buf[1024];
397                 snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/numa_node", port_cfg->pci_addr);
398                 FILE* numa_node_fd = fopen(buf, "r");
399                 if (numa_node_fd) {
400                         if (fgets(buf, sizeof(buf), numa_node_fd) == NULL) {
401                                 plog_warn("Failed to read numa_node for device %s\n", port_cfg->pci_addr);
402                         }
403                         port_cfg->socket = strtol(buf, 0, 0);
404                         if (port_cfg->socket == -1) {
405                                 plog_warn("System did not report numa_node for device %s\n", port_cfg->pci_addr);
406                         }
407                         fclose(numa_node_fd);
408                 }
409
410                 // In DPDK 18.08 vmxnet3 reports it supports IPV4 checksum, but packets does not go through when IPv4 cksum is enabled
411                 if ((!strcmp(port_cfg->short_name, "vmxnet3")) && (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)) {
412                         plog_info("\t\tDisabling IPV4 cksum on vmxnet3\n");
413                         port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_IPV4_CKSUM;
414                 }
415                 if ((!strcmp(port_cfg->short_name, "vmxnet3")) && (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) {
416                         plog_info("\t\tDisabling UDP cksum on vmxnet3\n");
417                         port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_UDP_CKSUM;
418                 }
419                 // Some OVS versions reports that they support UDP offload and no IPv4 offload, but fails when UDP offload is enabled
420                 if ((!strcmp(port_cfg->short_name, "virtio")) &&
421                         ((port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0) &&
422                         (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)) {
423                         plog_info("\t\tDisabling UDP cksum on virtio\n");
424                         port_cfg->disabled_tx_offload |= DEV_TX_OFFLOAD_UDP_CKSUM;
425                 }
426         }
427 }
428
429 /* Create rte ring-backed devices */
430 uint8_t init_rte_ring_dev(void)
431 {
432         uint8_t nb_ring_dev = 0;
433
434         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
435                 /* skip ports that are not enabled */
436                 if (!prox_port_cfg[port_id].active) {
437                         continue;
438                 }
439                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
440                 if (port_cfg->rx_ring[0] != '\0') {
441                         plog_info("\tRing-backed port %u: rx='%s' tx='%s'\n", port_id, port_cfg->rx_ring, port_cfg->tx_ring);
442
443                         struct rte_ring* rx_ring = rte_ring_lookup(port_cfg->rx_ring);
444                         PROX_PANIC(rx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->rx_ring, port_id);
445                         struct rte_ring* tx_ring = rte_ring_lookup(port_cfg->tx_ring);
446                         PROX_PANIC(tx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->tx_ring, port_id);
447
448                         int ret = rte_eth_from_rings(port_cfg->names[0], &rx_ring, 1, &tx_ring, 1, rte_socket_id());
449                         PROX_PANIC(ret != 0, "Failed to create eth_dev from rings for port %d\n", port_id);
450
451                         port_cfg->port_conf.intr_conf.lsc = 0; /* Link state interrupt not supported for ring-backed ports */
452
453                         nb_ring_dev++;
454                 }
455         }
456
457         return nb_ring_dev;
458 }
459
460 static void print_port_capa(struct prox_port_cfg *port_cfg)
461 {
462         uint8_t port_id;
463
464         port_id = port_cfg - prox_port_cfg;
465         plog_info("\t*** Initializing port %u ***\n", port_id);
466         plog_info("\t\tPort name is set to %s\n", port_cfg->names[0]);
467         plog_info("\t\tPort max RX/TX queue is %u/%u\n", port_cfg->max_rxq, port_cfg->max_txq);
468         plog_info("\t\tPort driver is %s\n", port_cfg->driver_name);
469 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0)
470         plog_info("\t\tSupported speed mask = 0x%x\n", port_cfg->dev_info.speed_capa);
471 #endif
472         if (port_cfg->max_link_speed != UINT32_MAX) {
473                 plog_info("\t\tHighest link speed capa = %d Mbps\n", port_cfg->max_link_speed);
474         }
475
476 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
477         plog_info("\t\tRX offload capa = 0x%lx = ", port_cfg->dev_info.rx_offload_capa);
478         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP)
479                 plog_info("VLAN STRIP | ");
480         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM)
481                 plog_info("IPV4 CKSUM | ");
482         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM)
483                 plog_info("UDP CKSUM | ");
484         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)
485                 plog_info("TCP CKSUM | ");
486         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO)
487                 plog_info("TCP LRO | ");
488         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP)
489                 plog_info("QINQ STRIP | ");
490         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
491                 plog_info("OUTER_IPV4_CKSUM | ");
492         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_MACSEC_STRIP)
493                 plog_info("MACSEC STRIP | ");
494         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_HEADER_SPLIT)
495                 plog_info("HEADER SPLIT | ");
496         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_FILTER)
497                 plog_info("VLAN FILTER | ");
498         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_EXTEND)
499                 plog_info("VLAN EXTEND | ");
500         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME)
501                 plog_info("JUMBO FRAME | ");
502 #if defined(DEV_RX_OFFLOAD_CRC_STRIP)
503         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_CRC_STRIP)
504                 plog_info("CRC STRIP | ");
505 #endif
506 #if defined(DEV_RX_OFFLOAD_KEEP_CRC)
507         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC)
508                 plog_info("KEEP CRC | ");
509 #endif
510         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCATTER)
511                 plog_info("SCATTER | ");
512         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP)
513                 plog_info("TIMESTAMP | ");
514         if (port_cfg->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY)
515                 plog_info("SECURITY ");
516         plog_info("\n");
517
518         plog_info("\t\tTX offload capa = 0x%lx = ", port_cfg->dev_info.tx_offload_capa);
519         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)
520                 plog_info("VLAN INSERT | ");
521         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)
522                 plog_info("IPV4 CKSUM | ");
523         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)
524                 plog_info("UDP CKSUM | ");
525         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)
526                 plog_info("TCP CKSUM | ");
527         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM)
528                 plog_info("SCTP CKSUM | ");
529         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO)
530                 plog_info("TCP TS0 | ");
531         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO)
532                 plog_info("UDP TSO | ");
533         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)
534                 plog_info("OUTER IPV4 CKSUM | ");
535         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT)
536                 plog_info("QINQ INSERT | ");
537         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO)
538                 plog_info("VLAN TNL TSO | ");
539         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO)
540                 plog_info("GRE TNL TSO | ");
541         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO)
542                 plog_info("IPIP TNL TSO | ");
543         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO)
544                 plog_info("GENEVE TNL TSO | ");
545         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MACSEC_INSERT)
546                 plog_info("MACSEC INSERT | ");
547         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MT_LOCKFREE)
548                 plog_info("MT LOCKFREE | ");
549         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MULTI_SEGS)
550                 plog_info("MULTI SEG | ");
551         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SECURITY)
552                 plog_info("SECURITY | ");
553         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO)
554                 plog_info("UDP TNL TSO | ");
555         if (port_cfg->dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO)
556                 plog_info("IP TNL TSO | ");
557         plog_info("\n");
558
559         plog_info("\t\trx_queue_offload_capa = 0x%lx\n", port_cfg->dev_info.rx_queue_offload_capa);
560         plog_info("\t\ttx_queue_offload_capa = 0x%lx\n", port_cfg->dev_info.tx_queue_offload_capa);
561         plog_info("\t\tflow_type_rss_offloads = 0x%lx\n", port_cfg->dev_info.flow_type_rss_offloads);
562         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);
563         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);
564 #endif
565 }
566
567 static void get_max_link_speed(struct prox_port_cfg *port_cfg)
568 {
569         port_cfg->max_link_speed = UINT32_MAX;
570
571 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0)
572         // virtio and vmxnet3 reports fake max_link_speed
573         if (strcmp(port_cfg->short_name, "vmxnet3") && strcmp(port_cfg->short_name, "virtio")) {
574                 // Get link_speed from highest capability from the port
575                 // This will be used by gen and lat for extrapolation purposes
576                 // The negotiated link_speed (as reported by rte_eth_link_get
577                 // or rte_eth_link_get_nowait) might be reported too late
578                 // and might result in wrong exrapolation, and hence should not be used
579                 // for extrapolation purposes
580                 if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_100G)
581                         port_cfg->max_link_speed = ETH_SPEED_NUM_100G;
582                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_56G)
583                         port_cfg->max_link_speed = ETH_SPEED_NUM_56G;
584                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_50G)
585                         port_cfg->max_link_speed = ETH_SPEED_NUM_50G;
586                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_40G)
587                         port_cfg->max_link_speed = ETH_SPEED_NUM_40G;
588                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_25G)
589                         port_cfg->max_link_speed = ETH_SPEED_NUM_25G;
590                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_20G)
591                         port_cfg->max_link_speed = ETH_SPEED_NUM_20G;
592                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_10G)
593                         port_cfg->max_link_speed = ETH_SPEED_NUM_10G;
594                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_5G)
595                         port_cfg->max_link_speed = ETH_SPEED_NUM_5G;
596                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_2_5G)
597                         port_cfg->max_link_speed = ETH_SPEED_NUM_2_5G;
598                 else if (port_cfg->dev_info.speed_capa & ETH_LINK_SPEED_1G)
599                         port_cfg->max_link_speed = ETH_SPEED_NUM_1G;
600                 else if (port_cfg->dev_info.speed_capa & (ETH_LINK_SPEED_100M_HD | ETH_LINK_SPEED_100M))
601                         port_cfg->max_link_speed = ETH_SPEED_NUM_100M;
602                 else if (port_cfg->dev_info.speed_capa & (ETH_LINK_SPEED_10M_HD | ETH_LINK_SPEED_10M))
603                         port_cfg->max_link_speed = ETH_SPEED_NUM_10M;
604
605         }
606 #endif
607 }
608
609 static void init_port(struct prox_port_cfg *port_cfg)
610 {
611         static char dummy_pool_name[] = "0_dummy";
612         struct rte_eth_link link;
613         uint8_t port_id;
614         int ret;
615
616         get_max_link_speed(port_cfg);
617         print_port_capa(port_cfg);
618         port_id = port_cfg - prox_port_cfg;
619         PROX_PANIC(port_cfg->n_rxq == 0 && port_cfg->n_txq == 0,
620                    "\t\t port %u is enabled but no RX or TX queues have been configured", port_id);
621
622         if (port_cfg->n_rxq == 0) {
623                 /* not receiving on this port */
624                 plog_info("\t\tPort %u had no RX queues, setting to 1\n", port_id);
625                 port_cfg->n_rxq = 1;
626                 uint32_t mbuf_size = TX_MBUF_SIZE;
627                 if (mbuf_size < port_cfg->min_rx_bufsize + RTE_PKTMBUF_HEADROOM + sizeof(struct rte_mbuf))
628                         mbuf_size = port_cfg->min_rx_bufsize + RTE_PKTMBUF_HEADROOM + sizeof(struct rte_mbuf);
629
630                 plog_info("\t\tAllocating dummy memory pool on socket %u with %u elements of size %u\n",
631                           port_cfg->socket, port_cfg->n_rxd, mbuf_size);
632                 port_cfg->pool[0] = rte_mempool_create(dummy_pool_name, port_cfg->n_rxd, mbuf_size,
633                                                        0,
634                                                        sizeof(struct rte_pktmbuf_pool_private),
635                                                        rte_pktmbuf_pool_init, NULL,
636                                                        prox_pktmbuf_init, 0,
637                                                        port_cfg->socket, 0);
638                 PROX_PANIC(port_cfg->pool[0] == NULL, "Failed to allocate dummy memory pool on socket %u with %u elements\n",
639                            port_cfg->socket, port_cfg->n_rxd);
640                 dummy_pool_name[0]++;
641         } else {
642                 // Most pmd should now support setting mtu
643                 if (port_cfg->mtu + PROX_RTE_ETHER_HDR_LEN + PROX_RTE_ETHER_CRC_LEN > port_cfg->max_rx_pkt_len) {
644                         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);
645                         port_cfg->mtu = port_cfg->max_rx_pkt_len;
646                 }
647                 plog_info("\t\tSetting MTU size to %u for port %u ...\n", port_cfg->mtu, port_id);
648                 ret = rte_eth_dev_set_mtu(port_id, port_cfg->mtu);
649                 if (ret)
650                         plog_err("\t\t\trte_eth_dev_set_mtu() failed on port %u: error %d\n", port_id, ret);
651
652                 if (port_cfg->n_txq == 0) {
653                         /* not sending on this port */
654                         plog_info("\t\tPort %u had no TX queues, setting to 1\n", port_id);
655                         port_cfg->n_txq = 1;
656                 }
657         }
658
659         if (port_cfg->n_rxq > 1)  {
660                 // Enable RSS if multiple receive queues
661                 if (strcmp(port_cfg->short_name, "virtio")) {
662                         port_cfg->port_conf.rxmode.mq_mode                      |= ETH_MQ_RX_RSS;
663                         port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key        = toeplitz_init_key;
664                         port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key_len    = TOEPLITZ_KEY_LEN;
665 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
666                         port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IP|ETH_RSS_UDP;
667 #else
668                         port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IPV4|ETH_RSS_NONF_IPV4_UDP;
669 #endif
670                 }
671         }
672
673         // Make sure that the requested RSS offload is supported by the PMD
674 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
675         port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf &= port_cfg->dev_info.flow_type_rss_offloads;
676 #endif
677         if (strcmp(port_cfg->short_name, "virtio")) {
678                 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);
679         } else {
680                 plog_info("\t\t Not enabling RSS on virtio port");
681         }
682
683         // rxmode such as hw src strip
684 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
685 #if defined (DEV_RX_OFFLOAD_CRC_STRIP)
686         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_CRC_STRIP);
687 #endif
688 #if defined (DEV_RX_OFFLOAD_KEEP_CRC)
689         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_KEEP_CRC);
690 #endif
691         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_JUMBO_FRAME);
692         CONFIGURE_RX_OFFLOAD(DEV_RX_OFFLOAD_VLAN_STRIP);
693 #else
694         if (port_cfg->requested_rx_offload & DEV_RX_OFFLOAD_CRC_STRIP) {
695                 port_cfg->port_conf.rxmode.hw_strip_crc = 1;
696         }
697         if (port_cfg->requested_rx_offload & DEV_RX_OFFLOAD_JUMBO_FRAME) {
698                 port_cfg->port_conf.rxmode.jumbo_frame = 1;
699         }
700 #endif
701
702         // IPV4, UDP, SCTP Checksums
703 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
704         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_IPV4_CKSUM);
705         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_UDP_CKSUM);
706         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_VLAN_INSERT);
707 #else
708         if ((port_cfg->dev_info.tx_offload_capa & (DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM)) == 0) {
709                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOOFFLOADS;
710                 plog_info("\t\tDisabling TX offloads as pmd reports that it does not support them)\n");
711         }
712         if (!strcmp(port_cfg->short_name, "vmxnet3")) {
713                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOXSUMSCTP;
714                 plog_info("\t\tDisabling SCTP offload on port %d as vmxnet3 does not support them\n", port_id);
715         }
716 #endif
717         // Multi Segments
718 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
719         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_MULTI_SEGS);
720 #else
721         if (!strcmp(port_cfg->short_name, "vmxnet3")) {
722                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
723                 plog_info("\t\tDisabling TX multsegs on port %d as vmxnet3 does not support them\n", port_id);
724         } else if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOMULTSEGS)
725                 plog_info("\t\tDisabling TX multsegs on port %d\n", port_id);
726         else
727                 plog_info("\t\tEnabling TX multsegs on port %d\n", port_id);
728
729         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS)
730                 plog_info("\t\tEnabling No TX offloads on port %d\n", port_id);
731         else
732                 plog_info("\t\tTX offloads enabled on port %d\n", port_id);
733 #endif
734
735         // Refcount
736 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
737         CONFIGURE_TX_OFFLOAD(DEV_TX_OFFLOAD_MBUF_FAST_FREE);
738 #else
739         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOREFCOUNT)
740                 plog_info("\t\tEnabling No refcnt on port %d\n", port_id);
741         else
742                 plog_info("\t\tRefcnt enabled on port %d\n", port_id);
743 #endif
744
745         plog_info("\t\tConfiguring port %u... with %u RX queues and %u TX queues\n",
746                   port_id, port_cfg->n_rxq, port_cfg->n_txq);
747
748         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);
749         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);
750
751         if (!strcmp(port_cfg->short_name, "ixgbe_vf") ||
752             !strcmp(port_cfg->short_name, "virtio") ||
753 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
754             !strcmp(port_cfg->short_name, "i40e") ||
755 #endif
756             !strcmp(port_cfg->short_name, "i40e_vf") ||
757             !strcmp(port_cfg->short_name, "avp") || /* Wind River */
758             !strcmp(port_cfg->driver_name, "") || /* NULL device */
759             !strcmp(port_cfg->short_name, "vmxnet3")) {
760                 port_cfg->port_conf.intr_conf.lsc = 0;
761                 plog_info("\t\tDisabling link state interrupt for vmxnet3/VF/virtio (unsupported)\n");
762         }
763
764         if (port_cfg->lsc_set_explicitely) {
765                 port_cfg->port_conf.intr_conf.lsc = port_cfg->lsc_val;
766                 plog_info("\t\tOverriding link state interrupt configuration to '%s'\n", port_cfg->lsc_val? "enabled" : "disabled");
767         }
768         if (port_cfg->n_txd < port_cfg->min_tx_desc) {
769                 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);
770                 port_cfg->n_txd = port_cfg->min_tx_desc;
771         }
772
773         if (port_cfg->n_rxd < port_cfg->min_rx_desc) {
774                 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);
775                 port_cfg->n_rxd = port_cfg->min_rx_desc;
776         }
777
778         if (port_cfg->n_txd > port_cfg->max_tx_desc) {
779                 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);
780                 port_cfg->n_txd = port_cfg->max_tx_desc;
781         }
782
783         if (port_cfg->n_rxd > port_cfg->max_rx_desc) {
784                 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);
785                 port_cfg->n_rxd = port_cfg->max_rx_desc;
786         }
787
788         ret = rte_eth_dev_configure(port_id, port_cfg->n_rxq,
789                                     port_cfg->n_txq, &port_cfg->port_conf);
790         PROX_PANIC(ret < 0, "\t\t\trte_eth_dev_configure() failed on port %u: %s (%d)\n", port_id, strerror(-ret), ret);
791
792         if (port_cfg->port_conf.intr_conf.lsc) {
793                 rte_eth_dev_callback_register(port_id, RTE_ETH_EVENT_INTR_LSC, lsc_cb, NULL);
794         }
795
796         plog_info("\t\tMAC address set to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
797
798         /* initialize TX queues first */
799         for (uint16_t queue_id = 0; queue_id < port_cfg->n_txq; ++queue_id) {
800                 plog_info("\t\tSetting up TX queue %u on socket %u with %u desc\n",
801                           queue_id, port_cfg->socket, port_cfg->n_txd);
802                 ret = rte_eth_tx_queue_setup(port_id, queue_id, port_cfg->n_txd,
803                                              port_cfg->socket, &port_cfg->tx_conf);
804                 PROX_PANIC(ret < 0, "\t\t\trte_eth_tx_queue_setup() failed on port %u: error %d\n", port_id, ret);
805         }
806
807         /* initialize RX queues */
808         for (uint16_t queue_id = 0; queue_id < port_cfg->n_rxq; ++queue_id) {
809                 plog_info("\t\tSetting up RX queue %u on port %u on socket %u with %u desc (pool 0x%p)\n",
810                           queue_id, port_id, port_cfg->socket,
811                           port_cfg->n_rxd, port_cfg->pool[queue_id]);
812                 ret = rte_eth_rx_queue_setup(port_id, queue_id,
813                                              port_cfg->n_rxd,
814                                              port_cfg->socket, &port_cfg->rx_conf,
815                                              port_cfg->pool[queue_id]);
816                 PROX_PANIC(ret < 0, "\t\t\trte_eth_rx_queue_setup() failed on port %u: error %s (%d)\n", port_id, strerror(-ret), ret);
817         }
818
819         plog_info("\t\tStarting up port %u ...", port_id);
820         ret = rte_eth_dev_start(port_id);
821
822         PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_start() failed on port %u: error %d\n", port_id, ret);
823         plog_info(" done: ");
824
825         if (prox_port_cfg[port_id].is_vdev) {
826                 for (int vlan_id = 0; vlan_id < prox_port_cfg[port_id].n_vlans; vlan_id++) {
827                         set_ip_address(prox_port_cfg[port_id].names[vlan_id], &prox_port_cfg[port_id].ip_addr[vlan_id].ip, prox_port_cfg[port_id].ip_addr[vlan_id].prefix);
828                 }
829         }
830         /* Getting link status can be done without waiting if Link
831            State Interrupt is enabled since in that case, if the link
832            is recognized as being down, an interrupt will notify that
833            it has gone up. */
834         if (port_cfg->port_conf.intr_conf.lsc)
835                 rte_eth_link_get_nowait(port_id, &link);
836         else
837                 rte_eth_link_get(port_id, &link);
838
839         port_cfg->link_up = link.link_status;
840         port_cfg->link_speed = link.link_speed;
841
842         if (link.link_status) {
843                 plog_info("Link Up - speed %'u Mbps - %s\n",
844                           link.link_speed,
845                           (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
846                           "full-duplex" : "half-duplex");
847         }
848         else {
849                 plog_info("Link Down\n");
850         }
851
852         if (port_cfg->promiscuous) {
853                 rte_eth_promiscuous_enable(port_id);
854                 plog_info("\t\tport %u in promiscuous mode\n", port_id);
855         }
856
857         if (strcmp(port_cfg->short_name, "ixgbe_vf") &&
858             strcmp(port_cfg->short_name, "i40e") &&
859             strcmp(port_cfg->short_name, "i40e_vf") &&
860             strcmp(port_cfg->short_name, "vmxnet3")) {
861                 for (uint8_t i = 0; i < port_cfg->n_rxq; ++i) {
862                         ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, i, i);
863                         if (ret) {
864                                 plog_info("\t\trte_eth_dev_set_rx_queue_stats_mapping() failed: error %d\n", ret);
865                         }
866                 }
867                 for (uint8_t i = 0; i < port_cfg->n_txq; ++i) {
868                         ret = rte_eth_dev_set_tx_queue_stats_mapping(port_id, i, i);
869                         if (ret) {
870                                 plog_info("\t\trte_eth_dev_set_tx_queue_stats_mapping() failed: error %d\n", ret);
871                         }
872                 }
873         }
874         if (port_cfg->nb_mc_addr) {
875                 rte_eth_allmulticast_enable(port_id);
876                 if ((ret = rte_eth_dev_set_mc_addr_list(port_id, port_cfg->mc_addr, port_cfg->nb_mc_addr)) != 0) {
877                         plog_err("\t\trte_eth_dev_set_mc_addr_list returns %d on port %u\n", ret, port_id);
878                         port_cfg->nb_mc_addr = 0;
879                         rte_eth_allmulticast_disable(port_id);
880                         plog_info("\t\tport %u NOT in multicast mode as failed to add mcast address\n", port_id);
881                 } else {
882                         plog_info("\t\trte_eth_dev_set_mc_addr_list(%d addr) on port %u\n", port_cfg->nb_mc_addr, port_id);
883                         plog_info("\t\tport %u in multicast mode\n", port_id);
884                 }
885         }
886 }
887
888 void init_port_all(void)
889 {
890         enum rte_proc_type_t proc_type;
891         proc_type = rte_eal_process_type();
892         if (proc_type == RTE_PROC_SECONDARY) {
893                 plog_info("\tSkipping port initialization as secondary process\n");
894                 return;
895         }
896         uint8_t max_port_idx = prox_last_port_active() + 1;
897
898         for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
899                 if (!prox_port_cfg[portid].active) {
900                         continue;
901                 }
902                 init_port(&prox_port_cfg[portid]);
903         }
904 }
905
906 void close_ports_atexit(void)
907 {
908         uint8_t max_port_idx = prox_last_port_active() + 1;
909
910         for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
911                 if (!prox_port_cfg[portid].active) {
912                         continue;
913                 }
914                 plog_info("Closing port %u\n", portid);
915                 rte_eth_dev_close(portid);
916         }
917
918         if (lcore_cfg == NULL)
919                 return;
920
921         struct lcore_cfg *lconf = NULL;
922         struct task_args *targ;
923         while (core_targ_next(&lconf, &targ, 0) == 0) {
924                 if (targ->pool) {
925                         rte_mempool_free(targ->pool);
926                         plog_info("freeing pool %p\n", targ->pool);
927                         targ->pool = NULL;
928                 }
929         }
930 }
931
932 void init_port_addr(void)
933 {
934         struct prox_port_cfg *port_cfg;
935         enum rte_proc_type_t proc_type;
936         int rc;
937
938         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
939                 if (!prox_port_cfg[port_id].active) {
940                         continue;
941                 }
942                 port_cfg = &prox_port_cfg[port_id];
943
944                 switch (port_cfg->type) {
945                 case PROX_PORT_MAC_HW:
946                         rte_eth_macaddr_get(port_id, &port_cfg->eth_addr);
947                         break;
948                 case PROX_PORT_MAC_RAND:
949                         prox_rte_eth_random_addr(port_cfg->eth_addr.addr_bytes);
950                         break;
951                 case PROX_PORT_MAC_SET:
952                         proc_type = rte_eal_process_type();
953                         if (proc_type == RTE_PROC_SECONDARY) {
954                                 plog_warn("\tport %u: unable to change port mac address as secondary process\n", port_id);
955                         } else if ((rc = rte_eth_dev_default_mac_addr_set(port_id, &port_cfg->eth_addr)) != 0)
956                                 plog_warn("\tport %u: failed to set mac address. Error = %d\n", port_id, rc);
957                         else
958                                 plog_info("Setting MAC to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
959                         break;
960                 }
961         }
962 }
963
964 int port_is_active(uint8_t port_id)
965 {
966         if (port_id > PROX_MAX_PORTS) {
967                 plog_info("requested port is higher than highest supported port ID (%u)\n", PROX_MAX_PORTS);
968                 return 0;
969         }
970
971         struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
972         if (!port_cfg->active) {
973                 plog_info("Port %u is not active\n", port_id);
974                 return 0;
975         }
976         return 1;
977 }