cea69a3723d383a79cc8461493fd75c660af1271
[samplevnf.git] / VNFs / DPPD-PROX / prox_port_cfg.c
1 /*
2 // Copyright (c) 2010-2017 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 "prox_port_cfg.h"
35 #include "prox_globals.h"
36 #include "log.h"
37 #include "quit.h"
38 #include "defaults.h"
39 #include "toeplitz.h"
40 #include "defines.h"
41 #include "prox_cksum.h"
42 #include "stats_irq.h"
43
44 struct prox_port_cfg prox_port_cfg[PROX_MAX_PORTS];
45 rte_atomic32_t lsc;
46
47 int prox_nb_active_ports(void)
48 {
49         int ret = 0;
50         for (uint32_t i = 0; i < PROX_MAX_PORTS; ++i) {
51                 ret += prox_port_cfg[i].active;
52         }
53         return ret;
54 }
55
56 int prox_last_port_active(void)
57 {
58         int ret = -1;
59         for (uint32_t i = 0; i < PROX_MAX_PORTS; ++i) {
60                 if (prox_port_cfg[i].active) {
61                         ret = i;
62                 }
63         }
64         return ret;
65 }
66
67 #if RTE_VERSION >= RTE_VERSION_NUM(17,11,0,0)
68 static int lsc_cb(__attribute__((unused)) uint16_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
69         __attribute__((unused)) void *ret_param)
70 #else
71 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
72 static int lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param,
73         __attribute__((unused)) void *ret_param)
74 #else
75 static void lsc_cb(__attribute__((unused)) uint8_t port_id, enum rte_eth_event_type type, __attribute__((unused)) void *param)
76 #endif
77 #endif
78 {
79         if (RTE_ETH_EVENT_INTR_LSC != type) {
80 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
81                 return -1;
82 #else
83                 return;
84 #endif
85         }
86
87         rte_atomic32_inc(&lsc);
88
89 #if RTE_VERSION >= RTE_VERSION_NUM(17,8,0,1)
90         return 0;
91 #endif
92 }
93
94 struct prox_pktmbuf_reinit_args {
95         struct rte_mempool *mp;
96         struct lcore_cfg   *lconf;
97 };
98
99 /* standard mbuf initialization procedure */
100 void prox_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigned i)
101 {
102         struct rte_mbuf *mbuf = _m;
103
104 #if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0)
105         mbuf->tx_offload = CALC_TX_OL(sizeof(struct ether_hdr), sizeof(struct ipv4_hdr));
106 #else
107         mbuf->pkt.vlan_macip.f.l2_len = sizeof(struct ether_hdr);
108         mbuf->pkt.vlan_macip.f.l3_len = sizeof(struct ipv4_hdr);
109 #endif
110
111         rte_pktmbuf_init(mp, opaque_arg, mbuf, i);
112 }
113
114 void prox_pktmbuf_reinit(void *arg, void *start, __attribute__((unused)) void *end, uint32_t idx)
115 {
116         struct prox_pktmbuf_reinit_args *init_args = arg;
117         struct rte_mbuf *m;
118         char* obj = start;
119
120         obj += init_args->mp->header_size;
121         m = (struct rte_mbuf*)obj;
122
123         prox_pktmbuf_init(init_args->mp, init_args->lconf, obj, idx);
124 }
125
126 /* initialize rte devices and check the number of available ports */
127 void init_rte_dev(int use_dummy_devices)
128 {
129         uint8_t nb_ports, port_id_max;
130         int port_id_last;
131         struct rte_eth_dev_info dev_info;
132
133         nb_ports = rte_eth_dev_count();
134         /* get available ports configuration */
135         PROX_PANIC(use_dummy_devices && nb_ports, "Can't use dummy devices while there are also real ports\n");
136
137         if (use_dummy_devices) {
138 #if (RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0))
139                 nb_ports = prox_last_port_active() + 1;
140                 plog_info("Creating %u dummy devices\n", nb_ports);
141
142                 char port_name[32] = "0dummy_dev";
143                 for (uint32_t i = 0; i < nb_ports; ++i) {
144 #if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
145                         rte_vdev_init(port_name, "size=ETHER_MIN_LEN,copy=0");
146 #else
147                         eth_dev_null_create(port_name, 0, ETHER_MIN_LEN, 0);
148 #endif
149                         port_name[0]++;
150                 }
151 #else
152         PROX_PANIC(use_dummy_devices, "Can't use dummy devices\n");
153 #endif
154         }
155         else if (prox_last_port_active() != -1) {
156                 PROX_PANIC(nb_ports == 0, "\tError: DPDK could not find any port\n");
157                 plog_info("\tDPDK has found %u ports\n", nb_ports);
158         }
159
160         if (nb_ports > PROX_MAX_PORTS) {
161                 plog_warn("\tWarning: I can deal with at most %u ports."
162                         " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
163
164                 nb_ports = PROX_MAX_PORTS;
165         }
166         port_id_max = nb_ports - 1;
167         port_id_last = prox_last_port_active();
168         PROX_PANIC(port_id_last > port_id_max,
169                    "\tError: invalid port(s) specified, last port index active: %d (max index is %d)\n",
170                    port_id_last, port_id_max);
171
172         /* Assign ports to PROX interfaces & Read max RX/TX queues per port */
173         for (uint8_t port_id = 0; port_id < nb_ports; ++port_id) {
174                 /* skip ports that are not enabled */
175                 if (!prox_port_cfg[port_id].active) {
176                         continue;
177                 }
178                 plog_info("\tGetting info for rte dev %u\n", port_id);
179                 rte_eth_dev_info_get(port_id, &dev_info);
180                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
181                 port_cfg->socket = -1;
182
183                 port_cfg->max_txq = dev_info.max_tx_queues;
184                 port_cfg->max_rxq = dev_info.max_rx_queues;
185                 port_cfg->max_rx_pkt_len = dev_info.max_rx_pktlen;
186                 port_cfg->min_rx_bufsize = dev_info.min_rx_bufsize;
187
188                 if (!dev_info.pci_dev)
189                         continue;
190
191                 snprintf(port_cfg->pci_addr, sizeof(port_cfg->pci_addr),
192                          "%04x:%02x:%02x.%1x", dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus, dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function);
193                 strncpy(port_cfg->driver_name, dev_info.driver_name, sizeof(port_cfg->driver_name));
194                 plog_info("\tPort %u : driver='%s' tx_queues=%d rx_queues=%d, max_rx_pktlen = %d, min_rx_bufsize = %d\n", port_id, !strcmp(port_cfg->driver_name, "")? "null" : port_cfg->driver_name, port_cfg->max_txq, port_cfg->max_rxq, port_cfg->max_rx_pkt_len, port_cfg->min_rx_bufsize);
195
196                 if (strncmp(port_cfg->driver_name, "rte_", 4) == 0) {
197                         strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
198                 } else if (strncmp(port_cfg->driver_name, "net_", 4) == 0) {
199                         strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name + 4, sizeof(port_cfg->short_name));
200                 } else {
201                         strncpy(port_cfg->short_name, prox_port_cfg[port_id].driver_name, sizeof(port_cfg->short_name));
202                 }
203                 char *ptr;
204                 if ((ptr = strstr(port_cfg->short_name, "_pmd")) != NULL) {
205                         *ptr = '\x0';
206                 }
207
208                 /* Try to find the device's numa node */
209                 char buf[1024];
210                 snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%s/numa_node", port_cfg->pci_addr);
211                 FILE* numa_node_fd = fopen(buf, "r");
212                 if (numa_node_fd) {
213                         if (fgets(buf, sizeof(buf), numa_node_fd) == NULL) {
214                                 plog_warn("Failed to read numa_node for device %s\n", port_cfg->pci_addr);
215                         }
216                         port_cfg->socket = strtol(buf, 0, 0);
217                         if (port_cfg->socket == -1) {
218                                 plog_warn("System did not report numa_node for device %s\n", port_cfg->pci_addr);
219                         }
220                         fclose(numa_node_fd);
221                 }
222
223                 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) {
224                         port_cfg->capabilities.tx_offload_cksum |= IPV4_CKSUM;
225                 }
226                 if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) {
227                         port_cfg->capabilities.tx_offload_cksum |= UDP_CKSUM;
228                 }
229         }
230 }
231
232 /* Create rte ring-backed devices */
233 uint8_t init_rte_ring_dev(void)
234 {
235         uint8_t nb_ring_dev = 0;
236
237         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
238                 /* skip ports that are not enabled */
239                 if (!prox_port_cfg[port_id].active) {
240                         continue;
241                 }
242                 struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
243                 if (port_cfg->rx_ring[0] != '\0') {
244                         plog_info("\tRing-backed port %u: rx='%s' tx='%s'\n", port_id, port_cfg->rx_ring, port_cfg->tx_ring);
245
246                         struct rte_ring* rx_ring = rte_ring_lookup(port_cfg->rx_ring);
247                         PROX_PANIC(rx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->rx_ring, port_id);
248                         struct rte_ring* tx_ring = rte_ring_lookup(port_cfg->tx_ring);
249                         PROX_PANIC(tx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->tx_ring, port_id);
250
251                         int ret = rte_eth_from_rings(port_cfg->name, &rx_ring, 1, &tx_ring, 1, rte_socket_id());
252                         PROX_PANIC(ret != 0, "Failed to create eth_dev from rings for port %d\n", port_id);
253
254                         port_cfg->port_conf.intr_conf.lsc = 0; /* Link state interrupt not supported for ring-backed ports */
255
256                         nb_ring_dev++;
257                 }
258         }
259
260         return nb_ring_dev;
261 }
262
263 static void init_port(struct prox_port_cfg *port_cfg)
264 {
265         static char dummy_pool_name[] = "0_dummy";
266         struct rte_eth_link link;
267         uint8_t port_id;
268         int ret;
269
270         port_id = port_cfg - prox_port_cfg;
271         plog_info("\t*** Initializing port %u ***\n", port_id);
272         plog_info("\t\tPort name is set to %s\n", port_cfg->name);
273         plog_info("\t\tPort max RX/TX queue is %u/%u\n", port_cfg->max_rxq, port_cfg->max_txq);
274         plog_info("\t\tPort driver is %s\n", port_cfg->driver_name);
275
276         PROX_PANIC(port_cfg->n_rxq == 0 && port_cfg->n_txq == 0,
277                    "\t\t port %u is enabled but no RX or TX queues have been configured", port_id);
278
279         if (port_cfg->n_rxq == 0) {
280                 /* not receiving on this port */
281                 plog_info("\t\tPort %u had no RX queues, setting to 1\n", port_id);
282                 port_cfg->n_rxq = 1;
283                 uint32_t mbuf_size = TX_MBUF_SIZE;
284                 plog_info("\t\tAllocating dummy memory pool on socket %u with %u elements of size %u\n",
285                           port_cfg->socket, port_cfg->n_rxd, mbuf_size);
286                 port_cfg->pool[0] = rte_mempool_create(dummy_pool_name, port_cfg->n_rxd, mbuf_size,
287                                                        0,
288                                                        sizeof(struct rte_pktmbuf_pool_private),
289                                                        rte_pktmbuf_pool_init, NULL,
290                                                        prox_pktmbuf_init, 0,
291                                                        port_cfg->socket, 0);
292                 PROX_PANIC(port_cfg->pool[0] == NULL, "Failed to allocate dummy memory pool on socket %u with %u elements\n",
293                            port_cfg->socket, port_cfg->n_rxd);
294                 dummy_pool_name[0]++;
295         } else {
296                 // Most pmd should now support setting mtu
297                 if (port_cfg->mtu + ETHER_HDR_LEN + ETHER_CRC_LEN > port_cfg->max_rx_pkt_len) {
298                         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);
299                         port_cfg->mtu = port_cfg->max_rx_pkt_len;
300                 }
301                 plog_info("\t\tSetting MTU size to %u for port %u ...\n", port_cfg->mtu, port_id);
302                 ret = rte_eth_dev_set_mtu(port_id, port_cfg->mtu);
303                 if (ret)
304                         plog_err("\t\t\trte_eth_dev_set_mtu() failed on port %u: error %d\n", port_id, ret);
305
306                 if (port_cfg->n_txq == 0) {
307                         /* not sending on this port */
308                         plog_info("\t\tPort %u had no TX queues, setting to 1\n", port_id);
309                         port_cfg->n_txq = 1;
310                 }
311         }
312
313         if (port_cfg->n_rxq > 1)  {
314                 // Enable RSS if multiple receive queues
315                 port_cfg->port_conf.rxmode.mq_mode                      |= ETH_MQ_RX_RSS;
316                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key        = toeplitz_init_key;
317                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key_len    = TOEPLITZ_KEY_LEN;
318 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
319                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IPV4|ETH_RSS_NONFRAG_IPV4_UDP;
320 #else
321                 port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IPV4|ETH_RSS_NONF_IPV4_UDP;
322 #endif
323         }
324         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOREFCOUNT)
325                 plog_info("\t\tEnabling No refcnt on port %d\n", port_id);
326         else
327                 plog_info("\t\tRefcnt enabled on port %d\n", port_id);
328
329         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOOFFLOADS)
330                 plog_info("\t\tEnabling No TX offloads on port %d\n", port_id);
331         else
332                 plog_info("\t\tTX offloads enabled on port %d\n", port_id);
333
334         if (port_cfg->tx_conf.txq_flags & ETH_TXQ_FLAGS_NOMULTSEGS)
335                 plog_info("\t\tEnabling No TX MultiSegs on port %d\n", port_id);
336         else
337                 plog_info("\t\tTX Multi segments enabled on port %d\n", port_id);
338
339         plog_info("\t\tConfiguring port %u... with %u RX queues and %u TX queues\n",
340                   port_id, port_cfg->n_rxq, port_cfg->n_txq);
341
342         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);
343         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);
344
345         if (!strcmp(port_cfg->short_name, "ixgbe_vf") ||
346             !strcmp(port_cfg->short_name, "virtio") ||
347 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
348             !strcmp(port_cfg->short_name, "i40e") ||
349 #endif
350             !strcmp(port_cfg->short_name, "i40e_vf") ||
351             !strcmp(port_cfg->short_name, "avp") || /* Wind River */
352             !strcmp(port_cfg->driver_name, "") || /* NULL device */
353             !strcmp(port_cfg->short_name, "vmxnet3")) {
354                 port_cfg->port_conf.intr_conf.lsc = 0;
355                 plog_info("\t\tDisabling link state interrupt for vmxnet3/VF/virtio (unsupported)\n");
356         }
357
358         if (port_cfg->lsc_set_explicitely) {
359                 port_cfg->port_conf.intr_conf.lsc = port_cfg->lsc_val;
360                 plog_info("\t\tOverriding link state interrupt configuration to '%s'\n", port_cfg->lsc_val? "enabled" : "disabled");
361         }
362         if (!strcmp(port_cfg->short_name, "vmxnet3")) {
363                 if (port_cfg->n_txd < 512) {
364                         // Vmxnet3 driver requires minimum 512 tx descriptors
365                         plog_info("\t\tNumber of TX descriptors is set to 512 (minimum required for vmxnet3\n");
366                         port_cfg->n_txd = 512;
367                 }
368         }
369
370         ret = rte_eth_dev_configure(port_id, port_cfg->n_rxq,
371                                     port_cfg->n_txq, &port_cfg->port_conf);
372         PROX_PANIC(ret < 0, "\t\t\trte_eth_dev_configure() failed on port %u: %s (%d)\n", port_id, strerror(-ret), ret);
373
374         if (port_cfg->port_conf.intr_conf.lsc) {
375                 rte_eth_dev_callback_register(port_id, RTE_ETH_EVENT_INTR_LSC, lsc_cb, NULL);
376         }
377
378         plog_info("\t\tMAC address set to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
379
380         /* initialize RX queues */
381         for (uint16_t queue_id = 0; queue_id < port_cfg->n_rxq; ++queue_id) {
382                 plog_info("\t\tSetting up RX queue %u on port %u on socket %u with %u desc (pool 0x%p)\n",
383                           queue_id, port_id, port_cfg->socket,
384                           port_cfg->n_rxd, port_cfg->pool[queue_id]);
385
386                 ret = rte_eth_rx_queue_setup(port_id, queue_id,
387                                              port_cfg->n_rxd,
388                                              port_cfg->socket, &port_cfg->rx_conf,
389                                              port_cfg->pool[queue_id]);
390
391                 PROX_PANIC(ret < 0, "\t\t\trte_eth_rx_queue_setup() failed on port %u: error %s (%d)\n", port_id, strerror(-ret), ret);
392         }
393         if (port_cfg->capabilities.tx_offload_cksum == 0) {
394                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOOFFLOADS;
395                 plog_info("\t\tDisabling TX offloads as pmd reports that it does not support them)\n");
396         }
397
398         if (!strcmp(port_cfg->short_name, "vmxnet3")) {
399                 port_cfg->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
400                 plog_info("\t\tDisabling multsegs on port %d as vmxnet3 does not support them\n", port_id);
401         }
402         /* initialize one TX queue per logical core on each port */
403         for (uint16_t queue_id = 0; queue_id < port_cfg->n_txq; ++queue_id) {
404                 plog_info("\t\tSetting up TX queue %u on socket %u with %u desc\n",
405                           queue_id, port_cfg->socket, port_cfg->n_txd);
406                 ret = rte_eth_tx_queue_setup(port_id, queue_id, port_cfg->n_txd,
407                                              port_cfg->socket, &port_cfg->tx_conf);
408                 PROX_PANIC(ret < 0, "\t\t\trte_eth_tx_queue_setup() failed on port %u: error %d\n", port_id, ret);
409         }
410
411         plog_info("\t\tStarting up port %u ...", port_id);
412         ret = rte_eth_dev_start(port_id);
413
414         PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_start() failed on port %u: error %d\n", port_id, ret);
415         plog_info(" done: ");
416
417         /* Getting link status can be done without waiting if Link
418            State Interrupt is enabled since in that case, if the link
419            is recognized as being down, an interrupt will notify that
420            it has gone up. */
421         if (port_cfg->port_conf.intr_conf.lsc)
422                 rte_eth_link_get_nowait(port_id, &link);
423         else
424                 rte_eth_link_get(port_id, &link);
425
426         port_cfg->link_up = link.link_status;
427         port_cfg->link_speed = link.link_speed;
428         if (link.link_status) {
429                 plog_info("Link Up - speed %'u Mbps - %s\n",
430                           link.link_speed,
431                           (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
432                           "full-duplex" : "half-duplex");
433         }
434         else {
435                 plog_info("Link Down\n");
436         }
437
438         if (port_cfg->promiscuous) {
439                 rte_eth_promiscuous_enable(port_id);
440                 plog_info("\t\tport %u in promiscuous mode\n", port_id);
441         }
442
443         if (strcmp(port_cfg->short_name, "ixgbe_vf") &&
444             strcmp(port_cfg->short_name, "i40e") &&
445             strcmp(port_cfg->short_name, "i40e_vf") &&
446             strcmp(port_cfg->short_name, "vmxnet3")) {
447                 for (uint8_t i = 0; i < 16; ++i) {
448                         ret = rte_eth_dev_set_rx_queue_stats_mapping(port_id, i, i);
449                         if (ret) {
450                                 plog_info("\t\trte_eth_dev_set_rx_queue_stats_mapping() failed: error %d\n", ret);
451                         }
452                         ret = rte_eth_dev_set_tx_queue_stats_mapping(port_id, i, i);
453                         if (ret) {
454                                 plog_info("\t\trte_eth_dev_set_tx_queue_stats_mapping() failed: error %d\n", ret);
455                         }
456                 }
457         }
458 }
459
460 void init_port_all(void)
461 {
462         uint8_t max_port_idx = prox_last_port_active() + 1;
463
464         for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
465                 if (!prox_port_cfg[portid].active) {
466                         continue;
467                 }
468                 init_port(&prox_port_cfg[portid]);
469         }
470 }
471
472 void close_ports_atexit(void)
473 {
474         uint8_t max_port_idx = prox_last_port_active() + 1;
475
476         for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
477                 if (!prox_port_cfg[portid].active) {
478                         continue;
479                 }
480                 rte_eth_dev_close(portid);
481         }
482 }
483
484 void init_port_addr(void)
485 {
486         struct prox_port_cfg *port_cfg;
487
488         for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
489                 if (!prox_port_cfg[port_id].active) {
490                         continue;
491                 }
492                 port_cfg = &prox_port_cfg[port_id];
493
494                 switch (port_cfg->type) {
495                 case PROX_PORT_MAC_HW:
496                         rte_eth_macaddr_get(port_id, &port_cfg->eth_addr);
497                         break;
498                 case PROX_PORT_MAC_RAND:
499                         eth_random_addr(port_cfg->eth_addr.addr_bytes);
500                         break;
501                 case PROX_PORT_MAC_SET:
502                         break;
503                 }
504         }
505 }
506
507 int port_is_active(uint8_t port_id)
508 {
509         if (port_id > PROX_MAX_PORTS) {
510                 plog_info("requested port is higher than highest supported port ID (%u)\n", PROX_MAX_PORTS);
511                 return 0;
512         }
513
514         struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
515         if (!port_cfg->active) {
516                 plog_info("Port %u is not active\n", port_id);
517                 return 0;
518         }
519         return 1;
520 }