diff --git a/freebsd/netinet/in_pcb.c b/freebsd/netinet/in_pcb.c index 11efa13a0..8bdc5db48 100644 --- a/freebsd/netinet/in_pcb.c +++ b/freebsd/netinet/in_pcb.c @@ -1114,13 +1114,26 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, return (error); } #else + struct ifaddr *ifa; + struct ifnet *ifp; + struct sockaddr_in ifp_sin; + 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) { + return (EADDRNOTAVAIL); + } + ifp = ifa->ifa_ifp; while (lport == 0) { int rss; error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport, cred); if (error) return (error); - rss = ff_rss_check(faddr.s_addr, laddr.s_addr, fport, lport); + rss = ff_rss_check(ifp->if_softc, faddr.s_addr, laddr.s_addr, + fport, lport); if (rss) { break; } diff --git a/lib/ff_api.symlist b/lib/ff_api.symlist index 555e0b0bb..257b7f38f 100644 --- a/lib/ff_api.symlist +++ b/lib/ff_api.symlist @@ -33,6 +33,7 @@ ff_kevent_do_each ff_veth_attach ff_veth_detach ff_veth_process_packet +ff_veth_softc_to_hostc ff_mbuf_gethdr ff_mbuf_get ff_mbuf_free diff --git a/lib/ff_dpdk_if.c b/lib/ff_dpdk_if.c index e20bb1aa5..8ac0781f4 100644 --- a/lib/ff_dpdk_if.c +++ b/lib/ff_dpdk_if.c @@ -23,6 +23,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ +#include #include #include @@ -158,6 +159,8 @@ static struct rte_mempool *pktmbuf_pool[NB_SOCKETS]; static struct rte_ring **arp_ring[RTE_MAX_LCORE]; +static uint16_t rss_reta_size[RTE_MAX_ETHPORTS]; + struct ff_msg_ring { char ring_name[2][RTE_RING_NAMESIZE]; /* ring[0] for lcore recv msg, other send */ @@ -534,6 +537,31 @@ init_kni(void) return 0; } +static void +set_rss_table(uint8_t port_id, uint16_t reta_size, uint16_t nb_queues) +{ + if (reta_size == 0) { + return; + } + + int reta_conf_size = RTE_MAX(1, reta_size / RTE_RETA_GROUP_SIZE); + struct rte_eth_rss_reta_entry64 reta_conf[reta_conf_size]; + + /* config HW indirection table */ + unsigned i, j, hash=0; + for (i = 0; i < reta_conf_size; i++) { + reta_conf[i].mask = ~0ULL; + for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) { + reta_conf[i].reta[j] = hash++ % nb_queues; + } + } + + if (rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size)) { + rte_exit(EXIT_FAILURE, "port[%d], failed to update rss table\n", + port_id); + } +} + static int init_port_start(void) { @@ -659,6 +687,15 @@ init_port_start(void) printf("TSO is disabled\n"); } + if (dev_info.reta_size) { + /* reta size must be power of 2 */ + assert((dev_info.reta_size & (dev_info.reta_size - 1)) == 0); + + rss_reta_size[port_id] = dev_info.reta_size; + printf("port[%d]: rss table size: %d\n", port_id, + dev_info.reta_size); + } + if (rte_eal_process_type() != RTE_PROC_PRIMARY) { continue; } @@ -689,6 +726,23 @@ init_port_start(void) return ret; } + if (nb_procs > 1) { + /* set HW rss hash function to Toeplitz. */ + if (!rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_HASH)) { + struct rte_eth_hash_filter_info info = {0}; + info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG; + info.info.global_conf.hash_func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; + + if (rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info) < 0) { + rte_exit(EXIT_FAILURE, "port[%d] set hash func failed\n", + port_id); + } + } + + set_rss_table(port_id, dev_info.reta_size, nb_procs); + } + /* Enable RX in promiscuous mode for the Ethernet device. */ if (ff_global_cfg.dpdk.promiscuous) { rte_eth_promiscuous_enable(port_id); @@ -1323,7 +1377,8 @@ toeplitz_hash(unsigned keylen, const uint8_t *key, } int -ff_rss_check(uint32_t saddr, uint32_t daddr, uint16_t sport, uint16_t dport) +ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr, + uint16_t sport, uint16_t dport) { struct lcore_conf *qconf = &lcore_conf; @@ -1331,6 +1386,9 @@ ff_rss_check(uint32_t saddr, uint32_t daddr, uint16_t sport, uint16_t dport) return 1; } + struct ff_dpdk_if_context *ctx = ff_veth_softc_to_hostc(softc); + uint16_t reta_size = rss_reta_size[ctx->port_id]; + uint8_t data[sizeof(saddr) + sizeof(daddr) + sizeof(sport) + sizeof(dport)]; @@ -1348,9 +1406,10 @@ ff_rss_check(uint32_t saddr, uint32_t daddr, uint16_t sport, uint16_t dport) bcopy(&dport, &data[datalen], sizeof(dport)); datalen += sizeof(dport); - uint32_t hash = toeplitz_hash(sizeof(default_rsskey_40bytes), default_rsskey_40bytes, datalen, data); + uint32_t hash = toeplitz_hash(sizeof(default_rsskey_40bytes), + default_rsskey_40bytes, datalen, data); - return (hash % qconf->nb_procs) == qconf->proc_id; + return (hash & (reta_size - 1) % qconf->nb_procs) == qconf->proc_id; } diff --git a/lib/ff_host_interface.h b/lib/ff_host_interface.h index 9b1656d9c..a6cdc6305 100644 --- a/lib/ff_host_interface.h +++ b/lib/ff_host_interface.h @@ -72,7 +72,8 @@ char *ff_getenv(const char *name); void ff_os_errno(int error); -int ff_rss_check(uint32_t saddr, uint32_t daddr, uint16_t sport, uint16_t dport); +int ff_rss_check(void *softc, uint32_t saddr, uint32_t daddr, + uint16_t sport, uint16_t dport); #endif diff --git a/lib/ff_veth.c b/lib/ff_veth.c index 6d7e76c0c..d1af12a63 100644 --- a/lib/ff_veth.c +++ b/lib/ff_veth.c @@ -413,4 +413,10 @@ ff_veth_detach(void *arg) return (0); } +void * +ff_veth_softc_to_hostc(void *softc) +{ + struct ff_veth_softc *sc = (struct ff_veth_softc *)softc; + return (void *)sc->host_ctx; +} diff --git a/lib/ff_veth.h b/lib/ff_veth.h index 920a491c1..7cbeecc3c 100644 --- a/lib/ff_veth.h +++ b/lib/ff_veth.h @@ -43,5 +43,7 @@ void ff_mbuf_tx_offload(void *m, struct ff_tx_offload *offload); void ff_veth_process_packet(void *arg, void *m); +void *ff_veth_softc_to_hostc(void *softc); + #endif /* ifndef _FSTACK_VETH_H */