More info see "rss_check" section in config.ini.
#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
#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;
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,
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);
return (EADDRINUSE);
}
} else {
-#ifndef FSTACK
struct sockaddr_in lsin, fsin;
-
bzero(&lsin, sizeof(lsin));
bzero(&fsin, sizeof(fsin));
lsin.sin_family = AF_INET;
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;
#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)
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
#include <stdint.h>
#include <getopt.h>
#include <ctype.h>
+#include <arpa/inet.h>
#include <rte_config.h>
#include <rte_string_fns.h>
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];
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)
} 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;
#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;
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;
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 {
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) {
}
#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");
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)
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;
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
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.
*
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 */