Fix toeplitz initialization key and rss key len for mlx4
[samplevnf.git] / VNFs / DPPD-PROX / prox_port_cfg.c
index 9798c59..b93198d 100644 (file)
 #include "stats_irq.h"
 #include "prox_compat.h"
 #include "rte_ethdev.h"
+#include "lconf.h"
 
 struct prox_port_cfg prox_port_cfg[PROX_MAX_PORTS];
+
 rte_atomic32_t lsc;
 
 int prox_nb_active_ports(void)
@@ -163,24 +165,40 @@ void prox_pktmbuf_reinit(void *arg, void *start, __attribute__((unused)) void *e
                 plog_info("\t\t%s disabled\n", #flag);\
         }\
 
+static inline uint32_t get_netmask(uint8_t prefix)
+{
+       if (prefix == 0)
+               return(~((uint32_t) -1));
+       else
+               return rte_cpu_to_be_32(~((1 << (32 - prefix)) - 1));
+}
 
-static void set_ip_address (char *devname, uint32_t *ip)
+static void set_ip_address(char *devname, uint32_t ip, uint8_t prefix)
 {
        struct ifreq ifreq;
        struct sockaddr_in in_addr;
        int fd, rc;
+       uint32_t netmask = get_netmask(prefix);
+       plog_info("Setting netmask to %x\n", netmask);
+       uint32_t ip_cpu = rte_be_to_cpu_32(ip);
+
+       fd = socket(AF_INET, SOCK_DGRAM, 0);
 
        memset(&ifreq, 0, sizeof(struct ifreq));
        memset(&in_addr, 0, sizeof(struct sockaddr_in));
 
        in_addr.sin_family = AF_INET;
-       in_addr.sin_addr = *(struct in_addr *)ip;
-       fd = socket(in_addr.sin_family, SOCK_DGRAM, 0);
+       in_addr.sin_addr = *(struct in_addr *)&ip_cpu;
 
-       strncpy(ifreq.ifr_name, devname, IFNAMSIZ);
+       prox_strncpy(ifreq.ifr_name, devname, IFNAMSIZ);
        ifreq.ifr_addr = *(struct sockaddr *)&in_addr;
        rc = ioctl(fd, SIOCSIFADDR, &ifreq);
-       PROX_PANIC(rc < 0, "Failed to set IP address %d on device %s: error = %d\n", *ip, devname, errno);
+       PROX_PANIC(rc < 0, "Failed to set IP address %x on device %s: error = %d (%s)\n", ip_cpu, devname, errno, strerror(errno));
+
+       in_addr.sin_addr = *(struct in_addr *)&netmask;
+       ifreq.ifr_netmask = *(struct sockaddr *)&in_addr;
+       rc = ioctl(fd, SIOCSIFNETMASK, &ifreq);
+       PROX_PANIC(rc < 0, "Failed to set netmask %x (prefix %d) on device %s: error = %d (%s)\n", netmask, prefix, devname, errno, strerror(errno));
        close(fd);
 }
 
@@ -192,31 +210,63 @@ void init_rte_dev(int use_dummy_devices)
        struct rte_eth_dev_info dev_info;
        const struct rte_pci_device *pci_dev;
 
+       for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
+               if (prox_port_cfg[port_id].active && (prox_port_cfg[port_id].virtual == 0) && (port_id >= prox_rte_eth_dev_count_avail())) {
+                       PROX_PANIC(1, "port %u used but only %u available\n", port_id, prox_rte_eth_dev_count_avail());
+               }
+       }
        for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
                if (!prox_port_cfg[port_id].active) {
                        continue;
                }
                struct prox_port_cfg* port_cfg = &prox_port_cfg[port_id];
+
+               prox_port_cfg[port_id].n_vlans = 0;
+               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])) {
+                       prox_port_cfg[port_id].n_vlans++;
+               }
+
                if (port_cfg->vdev[0]) {
-#if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
                        char name[MAX_NAME_SIZE], tap[MAX_NAME_SIZE];
                        snprintf(tap, MAX_NAME_SIZE, "net_tap%d", port_id);
+#if (RTE_VERSION > RTE_VERSION_NUM(17,5,0,1))
                        snprintf(name, MAX_NAME_SIZE, "iface=%s", port_cfg->vdev);
                        rc = rte_vdev_init(tap, name);
 #else
-                       rc = eth_dev_null_create(tap, name, PROX_RTE_ETHER_MIN_LEN, 0);
+                       PROX_PANIC(1, "vdev not supported in DPDK < 17.05\n");
 #endif
                        PROX_PANIC(rc != 0, "Unable to create device %s %s\n", "net tap", port_cfg->vdev);
-                       int vdev_port_id = rte_eth_dev_count() - 1;
+                       int vdev_port_id = prox_rte_eth_dev_count_avail() - 1;
                        PROX_PANIC(vdev_port_id >= PROX_MAX_PORTS, "Too many port defined %d >= %d\n", vdev_port_id, PROX_MAX_PORTS);
                        plog_info("\tCreating device %s, port %d\n", port_cfg->vdev, vdev_port_id);
+                       prox_port_cfg[vdev_port_id].is_vdev = 1;
                        prox_port_cfg[vdev_port_id].active = 1;
                        prox_port_cfg[vdev_port_id].dpdk_mapping = port_id;
                        prox_port_cfg[vdev_port_id].n_txq = 1;
-                       strncpy(prox_port_cfg[vdev_port_id].name, port_cfg->vdev, MAX_NAME_SIZE);
+                       prox_port_cfg[vdev_port_id].n_vlans = prox_port_cfg[port_id].n_vlans;
+
+                       for (uint32_t tag_id = 0; tag_id < prox_port_cfg[port_id].n_vlans; tag_id++) {
+                               prox_port_cfg[vdev_port_id].vlan_tags[tag_id] = prox_port_cfg[port_id].vlan_tags[tag_id];
+                               char command[1024];
+                               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]);
+                               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]);
+                               system(command);
+                               plog_info("\tRunning %s\n", command);
+                               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]);
+                       }
+                       if (prox_port_cfg[port_id].n_vlans == 0) {
+                               strncpy(prox_port_cfg[vdev_port_id].names[0], port_cfg->vdev, MAX_NAME_SIZE);
+                               prox_port_cfg[vdev_port_id].n_vlans = 1;
+                               prox_port_cfg[vdev_port_id].vlan_tags[0] = 0;
+                       }
+
                        prox_port_cfg[port_id].dpdk_mapping = vdev_port_id;
-                       prox_port_cfg[vdev_port_id].ip = rte_be_to_cpu_32(prox_port_cfg[port_id].ip);
-                       prox_port_cfg[port_id].ip = 0;  // So only vdev has an IP associated
+                       uint32_t i = 0;
+                       while ((i < PROX_MAX_VLAN_TAGS) && (prox_port_cfg[port_id].ip_addr[i].ip)) {
+                               prox_port_cfg[vdev_port_id].ip_addr[i].ip = prox_port_cfg[port_id].ip_addr[i].ip;
+                               prox_port_cfg[vdev_port_id].ip_addr[i].prefix = prox_port_cfg[port_id].ip_addr[i].prefix;
+                               i++;
+                       }
                        prox_port_cfg[vdev_port_id].type = prox_port_cfg[port_id].type;
                        if (prox_port_cfg[vdev_port_id].type == PROX_PORT_MAC_HW) {
                                // If DPDK port MAC set to HW, then make sure the vdev has the same MAC as DPDK port
@@ -227,6 +277,10 @@ void init_rte_dev(int use_dummy_devices)
                        } else
                                memcpy(&prox_port_cfg[vdev_port_id].eth_addr, &prox_port_cfg[port_id].eth_addr, sizeof(prox_port_cfg[port_id].eth_addr));
                }
+               if (prox_port_cfg[port_id].n_vlans == 0) {
+                       prox_port_cfg[port_id].n_vlans = 1;
+                       prox_port_cfg[port_id].vlan_tags[0] = 0;
+               }
        }
        nb_ports = prox_rte_eth_dev_count_avail();
        /* get available ports configuration */
@@ -261,17 +315,45 @@ void init_rte_dev(int use_dummy_devices)
 
                nb_ports = PROX_MAX_PORTS;
        }
+
+#if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
+       port_id_max = -1;
+       uint16_t id;
+       RTE_ETH_FOREACH_DEV(id) {
+               char name[256];
+               rte_eth_dev_get_name_by_port(id, name);
+               plog_info("\tFound DPDK port id %u %s\n", id, name);
+               if (id >= PROX_MAX_PORTS) {
+                       plog_warn("\tWarning: I can deal with at most %u ports."
+                                " Please update PROX_MAX_PORTS and recompile.\n", PROX_MAX_PORTS);
+               } else {
+                       prox_port_cfg[id].available = 1;
+                       if (id > port_id_max)
+                               port_id_max = id;
+               }
+       }
+#else
        port_id_max = nb_ports - 1;
+#endif
+
        port_id_last = prox_last_port_active();
        PROX_PANIC(port_id_last > port_id_max,
                   "\tError: invalid port(s) specified, last port index active: %d (max index is %d)\n",
                   port_id_last, port_id_max);
 
        /* Assign ports to PROX interfaces & Read max RX/TX queues per port */
-       for (uint8_t port_id = 0; port_id < nb_ports; ++port_id) {
+#if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
+       for (uint8_t port_id = 0; port_id <= port_id_last; ++port_id) {
+#else
+       for (uint8_t port_id = 0; port_id <= nb_ports; ++port_id) {
+#endif
                /* skip ports that are not enabled */
                if (!prox_port_cfg[port_id].active) {
                        continue;
+#if (RTE_VERSION >= RTE_VERSION_NUM(17,5,0,0))
+               } else if (prox_port_cfg[port_id].available == 0) {
+                       PROX_PANIC(1, "port %u enabled but not available\n", port_id);
+#endif
                }
                plog_info("\tGetting info for rte dev %u\n", port_id);
                rte_eth_dev_info_get(port_id, &dev_info);
@@ -369,7 +451,7 @@ uint8_t init_rte_ring_dev(void)
                        struct rte_ring* tx_ring = rte_ring_lookup(port_cfg->tx_ring);
                        PROX_PANIC(tx_ring == NULL, "Ring %s not found for port %d!\n", port_cfg->tx_ring, port_id);
 
-                       int ret = rte_eth_from_rings(port_cfg->name, &rx_ring, 1, &tx_ring, 1, rte_socket_id());
+                       int ret = rte_eth_from_rings(port_cfg->names[0], &rx_ring, 1, &tx_ring, 1, rte_socket_id());
                        PROX_PANIC(ret != 0, "Failed to create eth_dev from rings for port %d\n", port_id);
 
                        port_cfg->port_conf.intr_conf.lsc = 0; /* Link state interrupt not supported for ring-backed ports */
@@ -387,7 +469,7 @@ static void print_port_capa(struct prox_port_cfg *port_cfg)
 
        port_id = port_cfg - prox_port_cfg;
        plog_info("\t*** Initializing port %u ***\n", port_id);
-       plog_info("\t\tPort name is set to %s\n", port_cfg->name);
+       plog_info("\t\tPort name is set to %s\n", port_cfg->names[0]);
        plog_info("\t\tPort max RX/TX queue is %u/%u\n", port_cfg->max_rxq, port_cfg->max_txq);
        plog_info("\t\tPort driver is %s\n", port_cfg->driver_name);
 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,0)
@@ -582,21 +664,27 @@ static void init_port(struct prox_port_cfg *port_cfg)
 
        if (port_cfg->n_rxq > 1)  {
                // Enable RSS if multiple receive queues
-               port_cfg->port_conf.rxmode.mq_mode                      |= ETH_MQ_RX_RSS;
-               port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key        = toeplitz_init_key;
-               port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key_len    = TOEPLITZ_KEY_LEN;
+               if (strcmp(port_cfg->short_name, "virtio")) {
+                       port_cfg->port_conf.rxmode.mq_mode                      |= ETH_MQ_RX_RSS;
+                       port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key        = toeplitz_init_key;
+                       port_cfg->port_conf.rx_adv_conf.rss_conf.rss_key_len    = TOEPLITZ_KEY_LEN;
 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
-               port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IP|ETH_RSS_UDP;
+                       port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IP|ETH_RSS_UDP;
 #else
-               port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IPV4|ETH_RSS_NONF_IPV4_UDP;
+                       port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf         = ETH_RSS_IPV4|ETH_RSS_NONF_IPV4_UDP;
 #endif
+               }
        }
 
        // Make sure that the requested RSS offload is supported by the PMD
 #if RTE_VERSION >= RTE_VERSION_NUM(2,0,0,0)
        port_cfg->port_conf.rx_adv_conf.rss_conf.rss_hf &= port_cfg->dev_info.flow_type_rss_offloads;
 #endif
-       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);
+       if (strcmp(port_cfg->short_name, "virtio")) {
+               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);
+       } else {
+               plog_info("\t\t Not enabling RSS on virtio port");
+       }
 
        // rxmode such as hw src strip
 #if RTE_VERSION >= RTE_VERSION_NUM(18,8,0,1)
@@ -740,8 +828,10 @@ static void init_port(struct prox_port_cfg *port_cfg)
        PROX_PANIC(ret < 0, "\n\t\t\trte_eth_dev_start() failed on port %u: error %d\n", port_id, ret);
        plog_info(" done: ");
 
-       if (prox_port_cfg[port_id].ip) {
-               set_ip_address(prox_port_cfg[port_id].name, &prox_port_cfg[port_id].ip);
+       if (prox_port_cfg[port_id].is_vdev) {
+               for (int vlan_id = 0; vlan_id < prox_port_cfg[port_id].n_vlans; vlan_id++) {
+                       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);
+               }
        }
        /* Getting link status can be done without waiting if Link
           State Interrupt is enabled since in that case, if the link
@@ -803,6 +893,12 @@ static void init_port(struct prox_port_cfg *port_cfg)
 
 void init_port_all(void)
 {
+       enum rte_proc_type_t proc_type;
+       proc_type = rte_eal_process_type();
+       if (proc_type == RTE_PROC_SECONDARY) {
+               plog_info("\tSkipping port initialization as secondary process\n");
+               return;
+       }
        uint8_t max_port_idx = prox_last_port_active() + 1;
 
        for (uint8_t portid = 0; portid < max_port_idx; ++portid) {
@@ -821,13 +917,28 @@ void close_ports_atexit(void)
                if (!prox_port_cfg[portid].active) {
                        continue;
                }
+               plog_info("Closing port %u\n", portid);
                rte_eth_dev_close(portid);
        }
+
+       if (lcore_cfg == NULL)
+               return;
+
+       struct lcore_cfg *lconf = NULL;
+       struct task_args *targ;
+       while (core_targ_next(&lconf, &targ, 0) == 0) {
+               if (targ->pool) {
+                       rte_mempool_free(targ->pool);
+                       plog_info("freeing pool %p\n", targ->pool);
+                       targ->pool = NULL;
+               }
+       }
 }
 
 void init_port_addr(void)
 {
        struct prox_port_cfg *port_cfg;
+       enum rte_proc_type_t proc_type;
        int rc;
 
        for (uint8_t port_id = 0; port_id < PROX_MAX_PORTS; ++port_id) {
@@ -844,9 +955,13 @@ void init_port_addr(void)
                        prox_rte_eth_random_addr(port_cfg->eth_addr.addr_bytes);
                        break;
                case PROX_PORT_MAC_SET:
-                       plog_info("Setting MAC to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
-                       if ((rc = rte_eth_dev_default_mac_addr_set(port_id, &port_cfg->eth_addr)) != 0)
-                               plog_warn("port %u: failed to set mac address. Error = %d\n", port_id, rc);
+                       proc_type = rte_eal_process_type();
+                       if (proc_type == RTE_PROC_SECONDARY) {
+                               plog_warn("\tport %u: unable to change port mac address as secondary process\n", port_id);
+                       } else if ((rc = rte_eth_dev_default_mac_addr_set(port_id, &port_cfg->eth_addr)) != 0)
+                               plog_warn("\tport %u: failed to set mac address. Error = %d\n", port_id, rc);
+                       else
+                               plog_info("Setting MAC to "MAC_BYTES_FMT"\n", MAC_BYTES(port_cfg->eth_addr.addr_bytes));
                        break;
                }
        }