From e54aa4317b5d81f9f8643e491d8ec0ec1e72282a Mon Sep 17 00:00:00 2001 From: fengbojiang Date: Fri, 24 Oct 2025 17:37:45 +0800 Subject: [PATCH] Add the feature fo ff_rss_check table to improve the performance of ff_rss_check(). More info see "rss_check" section in config.ini. --- config.ini | 23 ++++ freebsd/netinet/in_pcb.c | 141 +++++++++++++------- freebsd/netinet/in_pcb.h | 3 + lib/ff_api.symlist | 5 +- lib/ff_config.c | 80 +++++++++++- lib/ff_config.h | 33 +++++ lib/ff_dpdk_if.c | 273 ++++++++++++++++++++++++++++++++++++++- lib/ff_host_interface.h | 11 ++ lib/ff_veth.c | 24 ++++ lib/ff_veth.h | 3 + 10 files changed, 547 insertions(+), 49 deletions(-) diff --git a/config.ini b/config.ini index 0219ae624..068b8b2aa 100644 --- a/config.ini +++ b/config.ini @@ -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. +# +# 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 diff --git a/freebsd/netinet/in_pcb.c b/freebsd/netinet/in_pcb.c index ed446df73..30b824a25 100644 --- a/freebsd/netinet/in_pcb.c +++ b/freebsd/netinet/in_pcb.c @@ -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; diff --git a/freebsd/netinet/in_pcb.h b/freebsd/netinet/in_pcb.h index 080d07cc7..4c83adf40 100644 --- a/freebsd/netinet/in_pcb.h +++ b/freebsd/netinet/in_pcb.h @@ -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) diff --git a/lib/ff_api.symlist b/lib/ff_api.symlist index 7e1cadb46..9fdf27397 100755 --- a/lib/ff_api.symlist +++ b/lib/ff_api.symlist @@ -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 diff --git a/lib/ff_config.c b/lib/ff_config.c index b64d11b02..0262a1f03 100644 --- a/lib/ff_config.c +++ b/lib/ff_config.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -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; diff --git a/lib/ff_config.h b/lib/ff_config.h index 81d9a47cd..6ce2028d2 100644 --- a/lib/ff_config.h +++ b/lib/ff_config.h @@ -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 { diff --git a/lib/ff_dpdk_if.c b/lib/ff_dpdk_if.c index ff189a8d1..ef9317c69 100644 --- a/lib/ff_dpdk_if.c +++ b/lib/ff_dpdk_if.c @@ -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; diff --git a/lib/ff_host_interface.h b/lib/ff_host_interface.h index 6d9c6de6c..a88988aa7 100644 --- a/lib/ff_host_interface.h +++ b/lib/ff_host_interface.h @@ -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 diff --git a/lib/ff_veth.c b/lib/ff_veth.c index c68a5c972..f5d50577d 100644 --- a/lib/ff_veth.c +++ b/lib/ff_veth.c @@ -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. * diff --git a/lib/ff_veth.h b/lib/ff_veth.h index 627662f69..87792ff04 100644 --- a/lib/ff_veth.h +++ b/lib/ff_veth.h @@ -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 */ -- 2.43.0