Skip to content

Commit fe7d190

Browse files
committed
feat(rss): add IPv6 RSS hash/port-range support (scheme A, independent v6 path)
Add ff_rss_check6/ff_rss_tbl6_*/ff_rss_adjust_sport6 with an independent v6 static table and thash ctx (36B tuple, sport@256bit), plus IPv6 rule parsing in rss_tbl config. Wire v6 into in_pcb_lport_dest as a parallel sa_family branch and into in6_pcbconnect/in6_pcbladdr, keeping the v4 RSS path byte-identical (diff +98/-0). Mandatory ff_rss_check6 re-verification; adds v6 unit tests + hit-rate probe (full-loop 100% landing).
1 parent 39f61e0 commit fe7d190

7 files changed

Lines changed: 812 additions & 4 deletions

File tree

freebsd/netinet/in_pcb.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,10 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
782782
struct ifnet *ifp = NULL;
783783
uint16_t rss_sel;
784784
int rss_fast;
785+
#ifdef INET6
786+
u_short rss6_first, rss6_last, *rss6_portrange;
787+
static int rss_tbl6_init = 0;
788+
#endif
785789

786790
lookupflags &= ~INPLOOKUP_LPORT_RSS_CHECK;
787791
#endif
@@ -848,6 +852,62 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
848852
dorandom = (V_ipport_randomized && first != last) ? 1 : 0;
849853

850854
if (rss_check_flag) {
855+
#ifdef INET6
856+
if (lsa->sa_family == AF_INET6) {
857+
/* 0.2 v6 RSS: parallel to v4, uses v6 table/check/adjust. */
858+
if (rss_tbl6_init == 0) {
859+
rss_ret = ff_rss_tbl6_set_portrange(first, last);
860+
rss_tbl6_init = (rss_ret < 0) ? -1 : 1;
861+
}
862+
863+
if (rss_tbl6_init == 1) {
864+
rss_ret = ff_rss_tbl6_get_portrange(faddr6->s6_addr,
865+
laddr6->s6_addr, fport, &rss6_first, &rss6_last,
866+
&rss6_portrange);
867+
if (rss_ret < 0) {
868+
if (rss_ret != -ENOENT)
869+
rss_tbl6_init = -1;
870+
} else {
871+
rss_match = 1;
872+
count = rss6_last - rss6_first + 1;
873+
if (dorandom)
874+
rss6_portrange[0] = rss6_first +
875+
(arc4random() % count);
876+
}
877+
}
878+
879+
if (!rss_match) {
880+
lsa->sa_len = sizeof(struct sockaddr_in6);
881+
ifa = ifa_ifwithnet(lsa, 0, RT_ALL_FIBS);
882+
if (ifa == NULL) {
883+
fsa->sa_len = sizeof(struct sockaddr_in6);
884+
ifa = ifa_ifwithnet(fsa, 0, RT_ALL_FIBS);
885+
if (ifa == NULL)
886+
return (EADDRNOTAVAIL);
887+
}
888+
ifp = ifa->ifa_ifp;
889+
890+
if (!(ifp->if_softc == NULL &&
891+
(ifp->if_flags & IFF_LOOPBACK))) {
892+
for (rss_fast = 0; rss_fast < 8; rss_fast++) {
893+
if (ff_rss_adjust_sport6(ifp->if_softc,
894+
faddr6->s6_addr, laddr6->s6_addr,
895+
fport, &rss_sel) != 0)
896+
break;
897+
lport = htons(rss_sel);
898+
if (in6_pcblookup_local(pcbinfo,
899+
&inp->in6p_laddr, lport, RT_ALL_FIBS,
900+
lookupflags, cred) == NULL) {
901+
*lastport = rss_sel;
902+
*lportp = lport;
903+
return (0);
904+
}
905+
}
906+
}
907+
}
908+
} else
909+
#endif
910+
{
851911
if (rss_tbl_init == 0) {
852912
rss_ret = ff_rss_tbl_set_portrange(first, last);
853913
rss_tbl_init = (rss_ret < 0) ? -1 : 1;
@@ -909,6 +969,7 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
909969
}
910970
}
911971
}
972+
}
912973

913974
if (!rss_check_flag || !rss_match) {
914975
if (dorandom)
@@ -926,6 +987,15 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
926987
if (count-- < 0) /* completely used? */
927988
return (EADDRNOTAVAIL);
928989
#ifdef FSTACK
990+
#ifdef INET6
991+
if (rss_check_flag && rss_match && lsa->sa_family == AF_INET6) {
992+
rss6_portrange[0]++;
993+
if (rss6_portrange[0] < rss6_first ||
994+
rss6_portrange[0] > rss6_last)
995+
rss6_portrange[0] = rss6_first;
996+
*lastport = rss6_portrange[rss6_portrange[0]];
997+
} else
998+
#endif
929999
if (rss_check_flag && rss_match) {
9301000
rss_portrange[0]++;
9311001
if (rss_portrange[0] < rss_first ||
@@ -975,6 +1045,22 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
9751045
tmpinp = in_pcblookup_local(pcbinfo,
9761046
laddr, lport, RT_ALL_FIBS,
9771047
lookupflags, cred);
1048+
#endif
1049+
#ifdef FSTACK
1050+
if (rss_check_flag && !rss_match &&
1051+
tmpinp == NULL && laddr6 != NULL &&
1052+
faddr6 != NULL) {
1053+
/* LOOPBACK does not support RSS. */
1054+
if (ifp->if_softc == NULL &&
1055+
(ifp->if_flags & IFF_LOOPBACK))
1056+
break;
1057+
if (ff_rss_check6(ifp->if_softc,
1058+
faddr6->s6_addr, laddr6->s6_addr,
1059+
fport, lport))
1060+
break;
1061+
/* not local queue: keep searching */
1062+
tmpinp++;
1063+
}
9781064
#endif
9791065
}
9801066
#endif

freebsd/netinet6/in6_pcb.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@
114114
#include <netinet6/in6_fib.h>
115115
#include <netinet6/scope6_var.h>
116116

117+
#ifdef FSTACK
118+
#include "ff_host_interface.h"
119+
#endif
120+
117121
SYSCTL_DECL(_net_inet6);
118122
SYSCTL_DECL(_net_inet6_ip6);
119123
VNET_DEFINE_STATIC(int, connect_in6addr_wild) = 1;
@@ -411,7 +415,15 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr_in6 *sin6,
411415
if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
412416
return (error);
413417

418+
#ifdef FSTACK
419+
in6a = in6addr_any;
420+
if (sas_required)
421+
ff_in_pcbladdr(AF_INET6, &sin6->sin6_addr,
422+
sin6->sin6_port, &in6a);
423+
if (sas_required && IN6_IS_ADDR_UNSPECIFIED(&in6a)) {
424+
#else
414425
if (sas_required) {
426+
#endif
415427
error = in6_selectsrc_socket(sin6, inp->in6p_outputopts,
416428
inp, inp->inp_cred, scope_ambiguous, &in6a, NULL);
417429
if (error)
@@ -505,7 +517,11 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred,
505517
error = in_pcb_lport_dest(inp,
506518
(struct sockaddr *) &laddr6, &inp->inp_lport,
507519
(struct sockaddr *) sin6, sin6->sin6_port, cred,
520+
#ifdef FSTACK
521+
INPLOOKUP_WILDCARD | INPLOOKUP_LPORT_RSS_CHECK);
522+
#else
508523
INPLOOKUP_WILDCARD);
524+
#endif
509525
if (error)
510526
return (error);
511527
}

lib/ff_config.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -910,8 +910,16 @@ rss_tbl_cfg_handler(struct ff_rss_check_cfg *cur)
910910

911911
/* Note: daddr must be include by port_id's addr or vip_addr, but here not check it now */
912912
rss_tbl_cfg_p[i].port_id = atoi(rss_tbl_4tuble_array[0]);
913-
inet_pton(AF_INET, rss_tbl_4tuble_array[1], (void *)&(rss_tbl_cfg_p[i].daddr));
914-
inet_pton(AF_INET, rss_tbl_4tuble_array[2], (void *)&(rss_tbl_cfg_p[i].saddr));
913+
/* v6 if the address text contains ':', else v4 (v4 path unchanged) */
914+
if (strchr(rss_tbl_4tuble_array[1], ':') != NULL) {
915+
rss_tbl_cfg_p[i].family = AF_INET6;
916+
inet_pton(AF_INET6, rss_tbl_4tuble_array[1], (void *)&(rss_tbl_cfg_p[i].daddr6));
917+
inet_pton(AF_INET6, rss_tbl_4tuble_array[2], (void *)&(rss_tbl_cfg_p[i].saddr6));
918+
} else {
919+
rss_tbl_cfg_p[i].family = AF_INET;
920+
inet_pton(AF_INET, rss_tbl_4tuble_array[1], (void *)&(rss_tbl_cfg_p[i].daddr));
921+
inet_pton(AF_INET, rss_tbl_4tuble_array[2], (void *)&(rss_tbl_cfg_p[i].saddr));
922+
}
915923
rss_tbl_cfg_p[i].sport = htons(atoi(rss_tbl_4tuble_array[3]));
916924
}
917925

lib/ff_config.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,11 @@ struct ff_bond_cfg {
231231
struct ff_rss_tbl_cfg {
232232
uint16_t port_id;
233233
uint16_t sport;
234-
uint32_t daddr; /* local */
235-
uint32_t saddr; /* remote */
234+
uint32_t daddr; /* local, v4 */
235+
uint32_t saddr; /* remote, v4 */
236+
uint8_t family; /* AF_INET (default) or AF_INET6 */
237+
uint8_t daddr6[16]; /* local, v6 */
238+
uint8_t saddr6[16]; /* remote, v6 */
236239
};
237240

238241
struct ff_rss_check_cfg {

0 commit comments

Comments
 (0)