From 61366e0a54935684ca3e17477c6367907285a5ff Mon Sep 17 00:00:00 2001
From: zhengjiebing <zhengjiebing_yewu@cmss.chinamobile.com>
Date: Mon, 17 Jun 2024 18:35:12 +0800
Subject: [PATCH] cfg: bond_slave_mac support pci addr

---
 src/lstack/core/lstack_cfg.c    | 35 +++++++++---------
 src/lstack/core/lstack_dpdk.c   | 63 ++++++++++++++++++++++++---------
 src/lstack/include/lstack_cfg.h | 16 ++++++++-
 3 files changed, 80 insertions(+), 34 deletions(-)

diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c
index 0e5fbf3..6ce862b 100644
--- a/src/lstack/core/lstack_cfg.c
+++ b/src/lstack/core/lstack_cfg.c
@@ -39,6 +39,7 @@
 #define LSTACK_CONF_ENV   "LSTACK_CONF_PATH"
 #define NUMA_CPULIST_PATH "/sys/devices/system/node/node%u/cpulist"
 #define DEV_MAC_LEN 17
+#define DEV_PCI_ADDR_LEN 12
 #define CPUS_MAX_NUM 256
 #define BOND_MIIMON_MIN 1
 #define BOND_MIIMON_MAX INT_MAX
@@ -188,6 +189,21 @@ static int32_t str_to_eth_addr(const char *src, unsigned char *dst)
     return 0;
 }
 
+static int32_t str_to_dev_addr(const char *src, struct dev_addr *dst)
+{
+    int32_t ret = 0;
+    if (strlen(src) ==  DEV_PCI_ADDR_LEN) {
+        /* str to pci addr */
+        ret = rte_pci_addr_parse(src, &dst->addr.pci_addr);
+        dst->addr_type = DEV_ADDR_TYPE_PCI;
+    } else {
+        /* str to mac addr */
+        ret = str_to_eth_addr(src, dst->addr.mac_addr.addr_bytes);
+        dst->addr_type = DEV_ADDR_TYPE_MAC;
+    }
+    return ret;
+}
+
 static int32_t parse_gateway_addr(void)
 {
     char *value;
@@ -1227,16 +1243,6 @@ static int32_t parse_bond_miimon(void)
     return ret;
 }
 
-static bool validate_bond_mac(uint8_t *mac_addr, struct rte_ether_addr *bond_slave_mac, int num_slaves)
-{
-    for (int i = 0; i < num_slaves; i++) {
-        if (memcmp(mac_addr, bond_slave_mac[i].addr_bytes, ETHER_ADDR_LEN) == 0) {
-            return true;
-        }
-    }
-    return false;
-}
-
 static int32_t parse_bond_slave_mac(void)
 {
     if (g_config_params.bond_mode == -1) {
@@ -1269,7 +1275,8 @@ static int32_t parse_bond_slave_mac(void)
             free(bond_slave_mac_tmp);
             return -EINVAL;
         }
-        ret = str_to_eth_addr(mac_addr, g_config_params.bond_slave_mac_addr[k].addr_bytes);
+
+        ret = str_to_dev_addr(mac_addr, &g_config_params.bond_slave_addr[k]);
         if (ret != 0) {
             LSTACK_PRE_LOG(LSTACK_ERR, "cfg: invalid device name %s ret=%d.\n", mac_addr, ret);
             free(bond_slave_mac_tmp);
@@ -1279,12 +1286,6 @@ static int32_t parse_bond_slave_mac(void)
         k = k + 1;
     }
     free(bond_slave_mac_tmp);
-    if (g_config_params.bond_mode == BONDING_MODE_ACTIVE_BACKUP) {
-        if (!validate_bond_mac(g_config_params.mac_addr, g_config_params.bond_slave_mac_addr, GAZELLE_MAX_BOND_NUM)) {
-            LSTACK_PRE_LOG(LSTACK_ERR, "cfg: devices must be in bond_slave_mac for BONDING_MODE_ACTIVE_BACKUP.\n");
-            return -EINVAL;
-        }
-    }
     return ret;
 }
 
diff --git a/src/lstack/core/lstack_dpdk.c b/src/lstack/core/lstack_dpdk.c
index 07fffe9..785431f 100644
--- a/src/lstack/core/lstack_dpdk.c
+++ b/src/lstack/core/lstack_dpdk.c
@@ -372,6 +372,23 @@ static int32_t ethdev_port_id(uint8_t *mac)
     return port_id;
 }
 
+static int32_t pci_to_port_id(struct rte_pci_addr *pci_addr)
+{
+    uint16_t port_id;
+    char device_name[RTE_DEV_NAME_MAX_LEN] = "";
+
+    rte_pci_device_name(pci_addr, device_name, RTE_DEV_NAME_MAX_LEN);
+
+    int ret = rte_eth_dev_get_port_by_name(device_name, &port_id);
+    if (ret < 0) {
+        LSTACK_LOG(ERR, LSTACK, "match failed: no NIC matches cfg:%04x:%02x:%02x.%x\n",
+            pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function);
+        return -EINVAL;
+    }
+
+    return port_id;
+}
+
 static int eth_params_rss(struct rte_eth_conf *conf, struct rte_eth_dev_info *dev_info)
 {
     int rss_enable = 0;
@@ -491,18 +508,25 @@ static void rss_setup(const int port_id, const uint16_t nb_queues)
     free(reta_conf);
 }
 
-int32_t dpdk_bond_primary_set(int port_id, int slave_port_id)
+int32_t dpdk_bond_primary_set(int port_id, int *slave_port_id)
 {
     int32_t primary_port_id = ethdev_port_id(get_global_cfg_params()->mac_addr);
-    if (slave_port_id == primary_port_id) {
-        int32_t ret = rte_eth_bond_primary_set(port_id, primary_port_id);
-        if (ret != 0) {
-            LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret);
-            return -1;
+    if (primary_port_id < 0) {
+        LSTACK_LOG(ERR, LSTACK, "cannot get the port id of the cfg\n");
+        return -1;
+    }
+    for (int i = 0; i < GAZELLE_MAX_BOND_NUM; i++) {
+        if (slave_port_id[i] == primary_port_id) {
+            int32_t ret = rte_eth_bond_primary_set(port_id, primary_port_id);
+            if (ret != 0) {
+                LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret);
+                return -1;
+            }
+            return ret;
         }
-        return ret;
     }
-    return 0;
+    LSTACK_LOG(ERR, LSTACK, "cfg: devices must be in bond_slave_mac for BONDING_MODE_ACTIVE_BACKUP.\n");
+    return -1;
 }
 
 int32_t dpdk_ethdev_init(int port_id)
@@ -687,12 +711,17 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count)
            LSTACK_LOG(ERR, LSTACK, "bond add slave devices failed, ret=%d\n", ret);
             return -1;
         }
-        if (cfg->bond_mode == BONDING_MODE_ACTIVE_BACKUP) {
-            dpdk_bond_primary_set(port_id, slave_port_id[i]);
+    }
+
+    if (cfg->bond_mode == BONDING_MODE_ACTIVE_BACKUP) {
+        ret = dpdk_bond_primary_set(port_id, slave_port_id);
+        if (ret != 0) {
+            LSTACK_LOG(ERR, LSTACK, "dpdk set bond primary port failed ret = %d\n", ret);
+            return -1;
         }
     }
 
-    if (get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) {
+    if (cfg->bond_mode == BONDING_MODE_8023AD) {
         ret = rte_eth_bond_8023ad_dedicated_queues_enable(port_id);
         if (ret < 0) {
             LSTACK_LOG(ERR, LSTACK, "dpdk enable 8023 dedicated queues failed ret = %d\n", ret);
@@ -717,8 +746,7 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count)
         return -1;
     }
 
-    if ((get_global_cfg_params()->bond_mode == BONDING_MODE_8023AD) ||
-        (get_global_cfg_params()->bond_mode == BONDING_MODE_ALB)) {
+    if ((cfg->bond_mode == BONDING_MODE_8023AD) || (cfg->bond_mode == BONDING_MODE_ALB)) {
         for (int i = 0; i < count; i++) {
             /* bond port promiscuous only enable primary port */
             /* we enable all ports */
@@ -742,17 +770,20 @@ static int dpdk_bond_create(uint8_t mode, int *slave_port_id, int count)
 int32_t init_dpdk_ethdev(void)
 {
     int32_t ret;
-    int slave_port_id[GAZELLE_MAX_BOND_NUM];
+    int slave_port_id[GAZELLE_MAX_BOND_NUM] = {-1};
     int port_id;
     struct cfg_params *cfg = get_global_cfg_params();
     int i;
 
     if (cfg->bond_mode >= 0) {
         for (i = 0; i < GAZELLE_MAX_BOND_NUM; i++) {
-            if (rte_is_zero_ether_addr(&cfg->bond_slave_mac_addr[i])) {
+            if (cfg->bond_slave_addr[i].addr_type == DEV_ADDR_TYPE_EMPTY) {
                 break;
+            } else if (cfg->bond_slave_addr[i].addr_type == DEV_ADDR_TYPE_MAC) {
+                slave_port_id[i] = ethdev_port_id(cfg->bond_slave_addr[i].addr.mac_addr.addr_bytes);
+            } else {
+                slave_port_id[i] = pci_to_port_id(&cfg->bond_slave_addr[i].addr.pci_addr);
             }
-            slave_port_id[i] = ethdev_port_id(cfg->bond_slave_mac_addr[i].addr_bytes);
             ret = dpdk_ethdev_init(slave_port_id[i]);
             if (ret < 0) {
                 LSTACK_LOG(ERR, LSTACK, "slave port(%d) init failed, ret=%d\n", slave_port_id[i], ret);
diff --git a/src/lstack/include/lstack_cfg.h b/src/lstack/include/lstack_cfg.h
index 94878de..21d9d83 100644
--- a/src/lstack/include/lstack_cfg.h
+++ b/src/lstack/include/lstack_cfg.h
@@ -16,6 +16,8 @@
 
 #include <lwip/ip_addr.h>
 #include <rte_ether.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
 
 #include "lstack_protocol_stack.h"
 #include "gazelle_opt.h"
@@ -52,6 +54,18 @@
 #define LSTACK_LPM_PKTS_IN_DETECT_MIN   5
 #define LSTACK_LPM_PKTS_IN_DETECT_MAX   65535
 
+#define DEV_ADDR_TYPE_EMPTY             0
+#define DEV_ADDR_TYPE_MAC               1
+#define DEV_ADDR_TYPE_PCI               2
+
+struct dev_addr {
+    uint8_t addr_type;      // 0:empty, 1:mac, 2:pci
+    union addr_union {
+        struct rte_ether_addr mac_addr;
+        struct rte_pci_addr pci_addr;
+    } addr;
+};
+
 struct secondary_attach_arg {
     uint8_t socket_num;
     uint64_t socket_size;
@@ -114,7 +128,7 @@ struct cfg_params {
     bool tuple_filter;
     int8_t bond_mode;
     int32_t bond_miimon;
-    struct rte_ether_addr bond_slave_mac_addr[GAZELLE_MAX_BOND_NUM];
+    struct dev_addr bond_slave_addr[GAZELLE_MAX_BOND_NUM];
     bool use_sockmap;
     bool udp_enable;
     struct cfg_nic_params nic;
-- 
2.33.0

