]> git.feebdaed.xyz Git - 0xmirror/f-stack.git/commitdiff
Add the feature fo ff_rss_check table to improve the performance of ff_rss_check().
authorfengbojiang <fengbojiang@tencent.com>
Fri, 24 Oct 2025 09:37:45 +0000 (17:37 +0800)
committerfengbojiang <fengbojiang@tencent.com>
Fri, 24 Oct 2025 09:37:45 +0000 (17:37 +0800)
More info see "rss_check" section in config.ini.

config.ini
freebsd/netinet/in_pcb.c
freebsd/netinet/in_pcb.h
lib/ff_api.symlist
lib/ff_config.c
lib/ff_config.h
lib/ff_dpdk_if.c
lib/ff_host_interface.h
lib/ff_veth.c
lib/ff_veth.h

index 0219ae624fd21c1efb3fde4e72875ec5badd6a3d..068b8b2aafa549cfe7492c22b67c03cc150685d4 100644 (file)
@@ -207,6 +207,29 @@ gateway=192.168.1.1
 #up_delay=10
 #down_delay=50
 
+# ff_rss_check table config section
+# To enable or disable static ff_rss_check table.
+# If enable it, F-Stack will init the table while the APP is starting.
+# Then the APP connect to a sever as client, it will try select a local port from the inited table first.
+#
+# This feature will greatly improve the performance of selecting local port
+# when the F-Stack application actively access remote services as a client and not set keep-alive.
+# If the local port is idle, it only needs to be selected once,
+# and no longer needs to be selected multiple times (the average number of times is about the total number of processes).
+# And the performance of selecting available local ports at a time is also improved compared to ff_rss_check().
+# If get rss local port failed, it will be fallback to ff_rss_check().
+#
+#    enable : 0 means disable, 1 means enable. Default 0.
+#    rss_tbl : Set 4-tuple for ff_rss_check table, Required argumnet.
+#              <porit_id> <daddr(local addr)> <saddr(remote addr)> <sport(remote port)>
+#              Separated by space in one 4-tuple, and separated by semicolon between multi 4-tuples.
+#              The max supported num of 2-tuple with saddr and sport is 4 * 4 = 16.
+#              The max supported num of daddr with one same saddr and sport is 4.
+#              So the max combination num of 4-tuple is 16 * 4 = 64, other config will be ignored.
+[rss_check]
+enable=0
+rss_tbl=0 192.168.1.1 192.168.2.1 80;0 192.168.1.1 192.168.2.1 443
+
 # Kni config: if enabled and method=reject,
 # all packets that do not belong to the following tcp_port and udp_port
 # will transmit to kernel; if method=accept, all packets that belong to
index ed446df731478cbea361c9a1c9d4c5bdc686a05f..30b824a253cd3332f594f990759eb5bc17ecd8e0 100644 (file)
@@ -700,6 +700,17 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
 #ifdef INET6
        struct in6_addr *laddr6 = NULL, *faddr6 = NULL;
 #endif
+#ifdef FSTACK
+       u_short rss_first, rss_last, *rss_portrange;
+       /* 0:not init, 1:init successed, -1:init failed */
+       static int rss_tbl_init = 0;
+       int rss_check_flag = lookupflags & INPLOOKUP_LPORT_RSS_CHECK;
+       int rss_ret, rss_port_idx, rss_match = 0;
+       struct ifaddr *ifa;
+       struct ifnet *ifp;
+
+       lookupflags = lookupflags & (~INPLOOKUP_LPORT_RSS_CHECK);
+#endif
 
        pcbinfo = inp->inp_pcbinfo;
 
@@ -780,20 +791,81 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
        tmpinp = NULL;
        lport = *lportp;
 
+#ifdef FSTACK
+       if (rss_check_flag) {
+               if (rss_tbl_init == 0) {
+                       rss_ret = ff_rss_tbl_set_portrange(first, last);
+                       if (rss_ret < 0)
+                               rss_tbl_init = -1;
+                       else
+                               rss_tbl_init = 1;
+               }
+
+               if (rss_tbl_init == 1) {
+                       rss_ret = ff_rss_tbl_get_portrange(faddr.s_addr, laddr.s_addr, fport,
+                           &rss_first, &rss_last, &rss_portrange);
+                       if (rss_ret < 0) {
+                               if (rss_ret != -ENOENT)
+                                       rss_tbl_init = -1;
+                       } else {
+                               /* [0] store last port idx */
+                               rss_match = 1;
+                               count = rss_last - rss_first + 1;
+                               if (dorandom)
+                                       rss_portrange[0] = rss_first + (arc4random() % (count));
+                       }
+               }
+
+               if (!rss_match) {
+                       lsa->sa_len = sizeof(struct sockaddr_in);
+                       ifa = ifa_ifwithnet(lsa, 0, RT_ALL_FIBS);
+                       if (ifa == NULL) {
+                               fsa->sa_len = sizeof(struct sockaddr_in);
+                               ifa = ifa_ifwithnet(fsa, 0, RT_ALL_FIBS);
+                               if ( ifa == NULL )
+                                       return (EADDRNOTAVAIL);
+                       }
+                       ifp = ifa->ifa_ifp;
+               }
+       }
+
+       if (!rss_check_flag || !rss_match) {
+#endif
        if (dorandom)
                *lastport = first + (arc4random() % (last - first));
 
        count = last - first;
+#ifdef FSTACK
+       }
+#endif
 
        do {
                if (count-- < 0)        /* completely used? */
                        return (EADDRNOTAVAIL);
+#ifdef FSTACK
+               if (rss_check_flag && rss_match) {
+                       rss_portrange[0]++;
+                       if (rss_portrange[0] < rss_first || rss_portrange[0] > rss_last)
+                           rss_portrange[0] = rss_first;
+                       *lastport = rss_portrange[rss_portrange[0]];
+               }
+
+               if (!rss_check_flag || !rss_match) {
+#endif
                ++*lastport;
                if (*lastport < first || *lastport > last)
                        *lastport = first;
+#ifdef FSTACK
+               }
+#endif
                lport = htons(*lastport);
 
-               if (fsa != NULL) {
+#ifdef FSTACK
+               if (!rss_check_flag && fsa != NULL)
+#else
+               if (fsa != NULL)
+#endif
+               {
 #ifdef INET
                        if (lsa->sa_family == AF_INET) {
                                tmpinp = in_pcblookup_hash_locked(pcbinfo,
@@ -818,8 +890,26 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
                        else
 #endif
 #ifdef INET
+                       {
                                tmpinp = in_pcblookup_local(pcbinfo, laddr,
                                    lport, lookupflags, cred);
+#ifdef FSTACK
+                               if (rss_check_flag && !rss_match && tmpinp == NULL) {
+                                       int rss;
+                                       /* Note:
+                                        * LOOPBACK not support rss.
+                                        */
+                                       if ((ifp->if_softc == NULL) && (ifp->if_flags & IFF_LOOPBACK))
+                                               break;
+                                       rss = ff_rss_check(ifp->if_softc, faddr.s_addr, laddr.s_addr,
+                                           fport, lport);
+                                       if (rss)
+                                               break;
+                                       else
+                                               tmpinp++; /* Set not NULL to find another lport */
+                               }
+#endif
+                       }
 #endif
                }
        } while (tmpinp != NULL);
@@ -1483,9 +1573,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
                        return (EADDRINUSE);
                }
        } else {
-#ifndef FSTACK
                struct sockaddr_in lsin, fsin;
-
                bzero(&lsin, sizeof(lsin));
                bzero(&fsin, sizeof(fsin));
                lsin.sin_family = AF_INET;
@@ -1494,52 +1582,13 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
                fsin.sin_addr = faddr;
                error = in_pcb_lport_dest(inp, (struct sockaddr *) &lsin,
                    &lport, (struct sockaddr *)& fsin, fport, cred,
+#ifndef FSTACK
                    INPLOOKUP_WILDCARD);
-               if (error)
-                       return (error);
 #else
-               struct ifaddr *ifa;
-               struct ifnet *ifp;
-               struct sockaddr_in ifp_sin;
-               unsigned loop_count = 0;
-               bzero(&ifp_sin, sizeof(ifp_sin));
-               ifp_sin.sin_addr.s_addr = laddr.s_addr;
-               ifp_sin.sin_family = AF_INET;
-               ifp_sin.sin_len = sizeof(ifp_sin);
-               ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS);
-               if (ifa == NULL) {
-                       ifp_sin.sin_addr.s_addr = faddr.s_addr;
-                       ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS);
-                       if ( ifa == NULL )
-                               return (EADDRNOTAVAIL);
-               }
-               ifp = ifa->ifa_ifp;
-               while (lport == 0) {
-                       int rss;
-                       error = in_pcb_lport(inp, &laddr, &lport, cred, INPLOOKUP_WILDCARD);
-                       if (error)
-                               return (error);
-                       /* Note:
-                        * LOOPBACK not support rss.
-                        */
-                       if ((ifp->if_softc == NULL) && (ifp->if_flags & IFF_LOOPBACK))
-                               break;
-                       rss = ff_rss_check(ifp->if_softc, faddr.s_addr, laddr.s_addr,
-                           fport, lport);
-                       if (rss) {
-                               break;
-                       }
-                       lport = 0;
-                       /* Note:
-                        * if all ports are completely used, just return.
-                        * this ugly code is not a correct way, it just lets loop quit.
-                        * we will fix it as soon as possible.
-                       */
-                       if (++loop_count >= 65535) {
-                               return (EADDRNOTAVAIL);
-                       }
-               }
+                   INPLOOKUP_WILDCARD | INPLOOKUP_LPORT_RSS_CHECK);
 #endif
+               if (error)
+                       return (error);
        }
        *laddrp = laddr.s_addr;
        *lportp = lport;
index 080d07cc7218fbfccf30e0ea9b57e903147937c5..4c83adf40385949a21a70d2caa861f619b5c3f0b 100644 (file)
@@ -761,6 +761,9 @@ int inp_so_options(const struct inpcb *inp);
 #define        INPLOOKUP_WILDCARD      0x00000001      /* Allow wildcard sockets. */
 #define        INPLOOKUP_RLOCKPCB      0x00000002      /* Return inpcb read-locked. */
 #define        INPLOOKUP_WLOCKPCB      0x00000004      /* Return inpcb write-locked. */
+#ifdef FSTACK
+#define        INPLOOKUP_LPORT_RSS_CHECK       0x80000000      /* F-Stack lport RSS check */
+#endif
 
 #define        INPLOOKUP_MASK  (INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB | \
                            INPLOOKUP_WLOCKPCB)
index 7e1cadb46d1bf0017b82bc73cca36bdb0b7cd9b2..9fdf2739792300f8c3a1339fb28e0f778178a19a 100755 (executable)
@@ -68,4 +68,7 @@ ff_swi_net_excute
 ff_adapt_user_thread_add
 ff_adapt_user_thread_exit
 ff_switch_curthread
-ff_restore_curthread
\ No newline at end of file
+ff_restore_curthread
+ff_rss_tbl_init
+ff_veth_get_softc
+ff_veth_free_softc
index b64d11b02e16d46d336806c58c8ab9254200fd0e..0262a1f03befabf8155b1a00e4d121ddc20aad11 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdint.h>
 #include <getopt.h>
 #include <ctype.h>
+#include <arpa/inet.h>
 #include <rte_config.h>
 #include <rte_string_fns.h>
 
@@ -515,7 +516,7 @@ ipfw_pr_cfg_handler(struct ff_port_cfg *cur_port_cfg, struct ff_vlan_cfg *cur_vl
                 vip_addr_str);
             free(vipfw_pr_cfg_p);
             return 1;
-        };
+        }
 
         vipfw_pr_cfg_p[i].addr = vip_addr_mask_array[0];
         vipfw_pr_cfg_p[i].netmask = vip_addr_mask_array[1];
@@ -855,6 +856,81 @@ bond_cfg_handler(struct ff_config *cfg, const char *section,
     return 1;
 }
 
+static int
+rss_tbl_cfg_handler(struct ff_config *cfg, struct ff_rss_check_cfg *cur)
+{
+    //vip cfg
+    int ret, nb_rss_tbl, i, j, k;
+    char *rss_tbl_array[FF_RSS_TBL_MAX_ENTRIES], *rss_tbl_4tuble_array[4], *rss_tbl_str;
+    struct ff_rss_tbl_cfg *rss_tbl_cfg_p;
+
+    rss_tbl_str = cur->rss_tbl_str;
+
+    ret = rte_strsplit(rss_tbl_str, strlen(rss_tbl_str), &rss_tbl_array[0], FF_RSS_TBL_MAX_ENTRIES, ';');
+    if (ret <= 0) {
+        fprintf(stdout, "rss_tbl_cfg_handler nb_rss_tbl is 0, not set rss_tbl or set invalid rss_tbl %s\n",
+            rss_tbl_str);
+        return 1;
+    }
+
+    nb_rss_tbl = ret;
+
+    rss_tbl_cfg_p = &cur->rss_tbl_cfgs[0];
+
+    for (i = 0; i < nb_rss_tbl; i++) {
+        rss_tbl_str = rss_tbl_array[i];
+        /* port_id, daddr(local), saddr(remote), sport */
+        ret = rte_strsplit(rss_tbl_str, strlen(rss_tbl_str), &rss_tbl_4tuble_array[0], 4, ' ');
+        if (ret != 4) {
+            fprintf(stdout, "rss_tbl_cfg_handler daddr/saddr/sport format error %s\n",
+                rss_tbl_str);
+            return 1;
+        }
+
+        /* Note: daddr must be include by port_id's addr or vip_addr, but here not check it now */
+        rss_tbl_cfg_p[i].port_id = atoi(rss_tbl_4tuble_array[0]);
+        inet_pton(AF_INET, rss_tbl_4tuble_array[1], (void *)&(rss_tbl_cfg_p[i].daddr));
+        inet_pton(AF_INET, rss_tbl_4tuble_array[2], (void *)&(rss_tbl_cfg_p[i].saddr));
+        rss_tbl_cfg_p[i].sport = htons(atoi(rss_tbl_4tuble_array[3]));
+    }
+
+    cur->nb_rss_tbl = nb_rss_tbl;
+
+    return 1;
+}
+
+static int
+rss_check_cfg_handler(struct ff_config *cfg, const char *section,
+    const char *name, const char *value)
+{
+    if (cfg->dpdk.port_cfgs == NULL && cfg->dpdk.vlan_cfgs == NULL) {
+        fprintf(stderr, "rss_check_cfg_handler: must config dpdk.port or dpdk.vlan first\n");
+        return 0;
+    }
+
+    if (cfg->dpdk.rss_check_cfgs == NULL) {
+        struct ff_rss_check_cfg *rcc = calloc(1, sizeof(struct ff_rss_check_cfg));
+        if (rcc == NULL) {
+            fprintf(stderr, "rss_check_cfg_handler malloc failed\n");
+            return 0;
+        }
+        cfg->dpdk.rss_check_cfgs = rcc;
+    }
+
+    struct ff_rss_check_cfg *cur = cfg->dpdk.rss_check_cfgs;
+
+    if (strcmp(name, "enable") == 0) {
+        cur->enable = atoi(value);
+    } else if (strcmp(name, "rss_tbl") == 0) {
+        cur->rss_tbl_str = strdup(value);
+        if (cur->rss_tbl_str) {
+            return rss_tbl_cfg_handler(cfg, cur);
+        }
+    }
+
+    return 1;
+}
+
 static int
 ini_parse_handler(void* user, const char* section, const char* name,
     const char* value)
@@ -955,6 +1031,8 @@ ini_parse_handler(void* user, const char* section, const char* name,
         } else if (strcmp(name, "savepath") == 0) {
             pconfig->pcap.save_path = strdup(value);
         }
+    } else if (strcmp(section, "rss_check") == 0) {
+        return rss_check_cfg_handler(pconfig, section, name, value);
     }
 
     return 1;
index 81d9a47cd66a19d0cc5c6bde1e6bfaca037fceba..6ce2028d2277438d9e03999938dbff1e9f955c0d 100644 (file)
@@ -61,6 +61,24 @@ extern char *dpdk_argv[DPDK_CONFIG_NUM + 1];
 #define KNI_TYPE_KNI        0
 #define KNI_TYPE_VIRTIO     1
 
+/* ff_rss_check table args */
+/* remote IP:PORT */
+#define FF_RSS_TBL_MAX_SADDR        (4)
+#define FF_RSS_TBL_MAX_SPORT        (4)
+#define FF_RSS_TBL_MAX_SADDR_MASK   (FF_RSS_TBL_MAX_SADDR - 1)
+#define FF_RSS_TBL_MAX_SPORT_MASK   (FF_RSS_TBL_MAX_SPORT - 1)
+/* local IP:PORT */
+#define FF_RSS_TBL_MAX_DADDR        (4)
+#define FF_RSS_TBL_MAX_DPORT        (65536)
+#define FF_RSS_TBL_MAX_DIP_MASK     (FF_RSS_TBL_MAX_DADDR - 1)
+#define FF_RSS_TBL_MAX_DPORT_MASK   (FF_RSS_TBL_MAX_DPORT - 1)
+
+#define FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES      (FF_RSS_TBL_MAX_SADDR * FF_RSS_TBL_MAX_SPORT)
+#define FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES_MASK (FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES - 1)
+
+#define FF_RSS_TBL_MAX_ENTRIES      (FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES * FF_RSS_TBL_MAX_DADDR)
+#define FF_RSS_TBL_MAX_ENTRIES_MASK (FF_RSS_TBL_MAX_ENTRIES - 1)
+
 struct ff_hw_features {
     uint8_t rx_csum;
     uint8_t rx_lro;
@@ -184,6 +202,20 @@ struct ff_bond_cfg {
     uint16_t down_delay;
 };
 
+struct ff_rss_tbl_cfg {
+    uint16_t port_id;
+    uint16_t sport;
+    uint32_t daddr; /* local */
+    uint32_t saddr; /* remote */
+};
+
+struct ff_rss_check_cfg {
+    int enable;
+    uint32_t nb_rss_tbl;
+    char *rss_tbl_str;
+    struct ff_rss_tbl_cfg rss_tbl_cfgs[FF_RSS_TBL_MAX_ENTRIES];
+};
+
 struct ff_freebsd_cfg {
     char *name;
     char *str;
@@ -246,6 +278,7 @@ struct ff_config {
         struct ff_vlan_cfg *vlan_cfgs;
         struct ff_vdev_cfg *vdev_cfgs;
         struct ff_bond_cfg *bond_cfgs;
+        struct ff_rss_check_cfg *rss_check_cfgs;
     } dpdk;
 
     struct {
index ff189a8d1440379064b4c97c4dbd8a45899c8c95..ef9317c69df4d5b9210b89e1971c6f136209881f 100644 (file)
@@ -146,6 +146,26 @@ static struct ff_top_args ff_top_status;
 static struct ff_traffic_args ff_traffic;
 extern void ff_hardclock(void);
 
+struct ff_rss_tbl_dip_type {
+    uint32_t daddr;
+    uint16_t first; /* The start port in portrange */
+    uint16_t last; /* The end port in portrange */
+    uint16_t first_idx; /* The idx of the start port in portrange */
+    uint16_t last_idx; /* The idx of the end port in portrange */
+    uint16_t num;
+    uint16_t dport[FF_RSS_TBL_MAX_DPORT + 1]; /* [0] used as the idx of last seleted port */
+} __rte_cache_aligned;
+
+struct ff_rss_tbl_type {
+    //enum ff_rss_tbl_init_type init;
+    uint32_t saddr;
+    uint16_t sport;
+    uint16_t num;
+    struct ff_rss_tbl_dip_type dip_tbl[FF_RSS_TBL_MAX_DADDR];
+} __rte_cache_aligned;
+static struct ff_rss_tbl_type ff_rss_tbl[FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES];
+
+
 static void
 ff_hardclock_job(__rte_unused struct rte_timer *timer,
     __rte_unused void *arg) {
@@ -1352,6 +1372,16 @@ ff_dpdk_init(int argc, char **argv)
     }
 #endif
 
+    if (ff_global_cfg.dpdk.rss_check_cfgs &&
+            ff_global_cfg.dpdk.rss_check_cfgs->enable) {
+        ret = ff_rss_tbl_init();
+        if (ret < 0) {
+            printf("ff_rss_tbl_init failed, disable it\n");
+        } else {
+            printf("ff_rss_tbl_init successed\n");
+        }
+    }
+
     ret = init_port_start();
     if (ret < 0) {
         rte_exit(EXIT_FAILURE, "init_port_start failed\n");
@@ -2433,6 +2463,247 @@ ff_regist_pcblddr_fun(pcblddr_func_t func)
     pcblddr_fun = func;
 }
 
+int
+ff_rss_tbl_init(void)
+{
+    uint32_t ori_idx, idx, ori_daddr_idx, daddr_idx;
+    uint32_t daddr, saddr;
+    uint16_t sport;
+    int prev_dport, stat, i, j, k;
+    void *sc;
+    struct ff_dpdk_if_context ctx;
+
+    memset(ff_rss_tbl, 0, sizeof(ff_rss_tbl));
+    //ff_rss_tbl.init = FF_RSS_TBL_INITING;
+
+    sc = ff_veth_get_softc(&ctx);
+    if (sc == NULL) {
+        printf("ff_veth_get_softc failed\n");
+        //ff_rss_tbl.init = FF_RSS_TBL_INIT_FAILED;
+        return -1;
+    }
+
+    for (i = 0; i < ff_global_cfg.dpdk.rss_check_cfgs->nb_rss_tbl; i++) {
+        struct ff_rss_tbl_cfg *rcc = &ff_global_cfg.dpdk.rss_check_cfgs->rss_tbl_cfgs[i];
+
+        ctx.port_id = rcc->port_id;
+        daddr = rcc->daddr;
+        saddr = rcc->saddr;
+        sport = rcc->sport;
+
+        /* Use DIR D to avoid getting the same idx while FF_RSS_TBL_MAX_DIP_MASK is very small*/
+        ori_idx = idx = ((saddr + (uint32_t)((uint8_t *)&saddr)[3]) ^ sport) & \
+            FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES_MASK;
+        ori_daddr_idx = daddr_idx = (daddr + (uint32_t)((uint8_t *)&daddr)[3]) & \
+            FF_RSS_TBL_MAX_DIP_MASK;
+
+        do {
+            if (ff_rss_tbl[idx].saddr == INADDR_ANY ||
+                    (ff_rss_tbl[idx].saddr == saddr &&
+                    ff_rss_tbl[idx].sport == sport)) {
+                break;
+            }
+
+            if (ff_rss_tbl[idx].saddr != saddr ||
+                    ff_rss_tbl[idx].sport != sport) {
+                idx++;
+                idx &= FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES_MASK;
+            }
+        } while (idx != ori_idx);
+
+        if (idx == ori_idx &&
+                ((ff_rss_tbl[idx].saddr != INADDR_ANY) &&
+                (ff_rss_tbl[idx].saddr != saddr ||
+                ff_rss_tbl[idx].sport != sport))) {
+            printf("There are too many 2-tuble(> %d) of saddrs(max %d) * sport(max %d),"
+                " this 4-tuple rss_tbl config will be ignored,"
+                 " idx %d, port_id %u, daddr %u, saddr %u, sport %u\n",
+                 FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES, FF_RSS_TBL_MAX_SADDR, FF_RSS_TBL_MAX_SPORT,
+                 i, ctx.port_id, daddr, saddr, sport);
+            //ff_rss_tbl.init = FF_RSS_TBL_INIT_FAILED;
+            goto IGNORE;
+            //ff_veth_free_softc(sc);
+            //return -1;
+        }
+
+        do {
+            if (ff_rss_tbl[idx].dip_tbl[daddr_idx].daddr == INADDR_ANY) {
+                break;
+            }
+
+            if (ff_rss_tbl[idx].dip_tbl[daddr_idx].daddr != daddr) {
+                daddr_idx++;
+                daddr_idx &= FF_RSS_TBL_MAX_DIP_MASK;
+            } else {
+                /* Dup 3-tuple */
+                printf("Duplicate ff rss table 3-tuple,"
+                    " this 4-tuple rss_tbl config will be ignored,"
+                     " port_id %u, daddr %u, saddr %u, sport %u\n",
+                     ctx.port_id, daddr, saddr, sport);
+                goto IGNORE;
+            }
+        } while (daddr_idx != ori_daddr_idx);
+
+        if (daddr_idx == ori_daddr_idx && ff_rss_tbl[idx].dip_tbl[daddr_idx].daddr != INADDR_ANY) {
+            printf("There are too many daddrs(> %d) with same saddr and sport,"
+                " this 4-tuple rss_tbl config will be ignored,"
+                 " idx %d, port_id %u, daddr %u, saddr %u, sport %u\n",
+                 i, FF_RSS_TBL_MAX_DADDR, ctx.port_id, daddr, saddr, sport);
+            goto IGNORE;
+            //return -1; /* Not used now */
+        }
+
+        /* The idx of port start form 1, 0 used as the idx of last selected port */
+        k = 1;
+        prev_dport = -1;
+        ff_rss_tbl[idx].dip_tbl[daddr_idx].dport[0] = k;
+        ff_rss_tbl[idx].dip_tbl[daddr_idx].first_idx = k;
+        for (j = 0; j < FF_RSS_TBL_MAX_DPORT; j++) {
+            stat = ff_rss_check(sc, saddr, daddr, sport, htons(j));
+            if (stat) {
+                ff_rss_tbl[idx].dip_tbl[daddr_idx].num++;
+                ff_rss_tbl[idx].dip_tbl[daddr_idx].dport[k++] = j;
+                if (prev_dport == -1) {
+                    ff_rss_tbl[idx].dip_tbl[daddr_idx].first = j;
+                }
+                prev_dport = j;
+            }
+        }
+        ff_rss_tbl[idx].dip_tbl[daddr_idx].last_idx = k - 1;
+        ff_rss_tbl[idx].dip_tbl[daddr_idx].last = prev_dport;
+        ff_rss_tbl[idx].dip_tbl[daddr_idx].daddr = daddr;
+
+        ff_rss_tbl[idx].saddr = saddr;
+        ff_rss_tbl[idx].sport = sport;
+        ff_rss_tbl[idx].num++;
+
+IGNORE:
+        // do nothing
+        ;
+    }
+
+    //ff_rss_tbl.init = FF_RSS_TBL_INITED;
+
+    ff_veth_free_softc(sc);
+
+    return 0;
+
+}
+
+int
+ff_rss_tbl_set_portrange(uint16_t first, uint16_t last)
+{
+    int i, j, k;
+
+    if (first > last || !ff_global_cfg.dpdk.rss_check_cfgs ||
+            ff_global_cfg.dpdk.rss_check_cfgs->enable == 0) {
+        return -1;
+    }
+
+    for (i = 0; i < FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES; i++) {
+        if (ff_rss_tbl[i].saddr == INADDR_ANY) {
+            continue;
+        }
+
+        for(j = 0; j < FF_RSS_TBL_MAX_DADDR; j++) {
+            if (ff_rss_tbl[i].dip_tbl[j].daddr == INADDR_ANY) {
+                continue;
+            }
+
+            ff_rss_tbl[i].dip_tbl[j].first = first;
+            ff_rss_tbl[i].dip_tbl[j].last = last;
+
+            ff_rss_tbl[i].dip_tbl[j].first_idx = 0;
+            for (k = 1; k <= ff_rss_tbl[i].dip_tbl[j].num; k++) {
+                if (ff_rss_tbl[i].dip_tbl[j].first_idx == 0 &&
+                        ff_rss_tbl[i].dip_tbl[j].dport[k] >= first) {
+                    ff_rss_tbl[i].dip_tbl[j].first_idx = k;
+                    if (ff_rss_tbl[i].dip_tbl[j].dport[ff_rss_tbl[i].dip_tbl[j].num] < last) {
+                        /* ff_rss_tbl_init set last_idx as ff_rss_tbl[i].dip_tbl[j].num already. */
+                        break;
+                    }
+                    if (first == last) {
+                        ff_rss_tbl[i].dip_tbl[j].last_idx = k;
+                        break;
+                    }
+                }
+                if (ff_rss_tbl[i].dip_tbl[j].dport[k] == last) {
+                    ff_rss_tbl[i].dip_tbl[j].last_idx = k;
+                    break;
+                }
+                if (ff_rss_tbl[i].dip_tbl[j].dport[k] > last) {
+                    ff_rss_tbl[i].dip_tbl[j].last_idx = k > 1 ? k -1 : k;
+                    break;
+                }
+            }
+
+            if (ff_rss_tbl[i].dip_tbl[j].first_idx == 0 ||
+                    ff_rss_tbl[i].dip_tbl[j].last_idx < ff_rss_tbl[i].dip_tbl[j].first_idx) {
+                fprintf(stderr, "ff_rss_tbl_set_portrange failed, first %u, last %u\n",
+                    first, last);
+                return -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+int
+ff_rss_tbl_get_portrange(uint32_t saddr, uint32_t daddr, uint16_t sport,
+    uint16_t *rss_first, uint16_t *rss_last, uint16_t **rss_portrange)
+{
+    uint32_t ori_idx, idx, ori_daddr_idx, daddr_idx;
+    int i;
+
+    if (!ff_global_cfg.dpdk.rss_check_cfgs ||
+            ff_global_cfg.dpdk.rss_check_cfgs->enable == 0) {
+        return -1;
+    }
+
+    ori_idx = idx = ((saddr + (uint32_t)((uint8_t *)&saddr)[3]) ^ sport) & \
+        FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES_MASK;
+    do {
+        /* If not inited, no need to continue find */
+        if (ff_rss_tbl[idx].saddr == INADDR_ANY) {
+            return -ENOENT;
+        }
+
+        if (ff_rss_tbl[idx].saddr == saddr && ff_rss_tbl[idx].sport == sport) {
+            ori_daddr_idx = daddr_idx = (daddr + (uint32_t)((uint8_t *)&daddr)[3]) & \
+                FF_RSS_TBL_MAX_DIP_MASK;
+            do {
+                if (ff_rss_tbl[idx].dip_tbl[daddr_idx].daddr == INADDR_ANY) {
+                    return -ENOENT;
+                }
+
+                if (ff_rss_tbl[idx].dip_tbl[daddr_idx].daddr == daddr) {
+                    *rss_first = ff_rss_tbl[idx].dip_tbl[daddr_idx].first_idx;
+                    *rss_last = ff_rss_tbl[idx].dip_tbl[daddr_idx].last_idx;
+                    *rss_portrange = &ff_rss_tbl[idx].dip_tbl[daddr_idx].dport[0];
+                    return 0;
+                }
+
+                daddr_idx++;
+                daddr_idx &= FF_RSS_TBL_MAX_DIP_MASK;
+            } while (daddr_idx != ori_daddr_idx);
+
+            if (daddr_idx == ori_daddr_idx) {
+                return -ENOENT;
+            }
+        }
+
+        idx++;
+        idx &= FF_RSS_TBL_MAX_SADDR_SPORT_ENTRIES_MASK;
+    } while (idx != ori_idx);
+
+    if (idx == ori_idx) {
+        return -ENOENT;
+    }
+
+    return -ENOENT;
+}
+
 int
 ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
     uint16_t sport, uint16_t dport)
@@ -2449,7 +2720,7 @@ ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
     uint16_t queueid = qconf->tx_queue_id[ctx->port_id];
 
     uint8_t data[sizeof(saddr) + sizeof(daddr) + sizeof(sport) +
-        sizeof(dport)];
+            sizeof(dport)];
 
     unsigned datalen = 0;
 
index 6d9c6de6c3694c9c00ba33eea4271a24604a2e6c..a88988aa7424804cf4c879fee5e64a0f07527855 100644 (file)
@@ -78,6 +78,17 @@ int ff_in_pcbladdr(uint16_t family, void *faddr, uint16_t fport, void *laddr);
 int ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr,
     uint16_t sport, uint16_t dport);
 
+int ff_rss_tbl_init(void);
+int ff_rss_tbl_set_portrange(uint16_t first, uint16_t last);
+/*
+ * return value:
+ * 0: finded
+ * -1: Serious error, can't call it further.
+ * -ENOENT(-2): Not finded, can call it further.
+ */
+int ff_rss_tbl_get_portrange(uint32_t saddr, uint32_t daddr, uint16_t sport,
+    uint16_t *rss_first, uint16_t *rss_last, uint16_t **rss_portrange);
+
 void ff_swi_net_excute(void);
 
 #endif
index c68a5c972f4f7d875fc8c9049f72ac94c011097f..f5d50577de911fa667b47ca8402086ee3d307881 100644 (file)
@@ -1054,6 +1054,30 @@ ff_veth_softc_to_hostc(void *softc)
     return (void *)sc->host_ctx;
 }
 
+void *
+ff_veth_get_softc(void *host_ctx)
+{
+    struct ff_veth_softc *sc = NULL;
+
+    sc = malloc(sizeof(struct ff_veth_softc), M_DEVBUF, M_WAITOK);
+    if (NULL == sc) {
+        printf("ff_veth_softc allocation failed\n");
+        return NULL;
+    }
+    memset(sc, 0, sizeof(struct ff_veth_softc));
+
+    sc->host_ctx = host_ctx;
+
+    return sc;
+}
+
+void
+ff_veth_free_softc(void *softc)
+{
+    if (softc)
+        free(softc, M_DEVBUF);
+}
+
 /********************
 *  get next mbuf's addr, current mbuf's data and datalen.
 *
index 627662f69777f2818453fdf8e36ec07d6dc4e2d6..87792ff047ae7ae84df75c483649c925feb8feb4 100644 (file)
@@ -48,6 +48,9 @@ void ff_veth_process_packet(void *arg, void *m);
 
 void *ff_veth_softc_to_hostc(void *softc);
 
+void *ff_veth_get_softc(void *host_ctx);
+void ff_veth_free_softc(void *softc);
+
 void ff_mbuf_set_vlan_info(void *hdr, uint16_t vlan_tci);
 
 #endif /* ifndef _FSTACK_VETH_H */