107107
108108#include <security/mac/mac_framework.h>
109109
110+ #ifdef FSTACK
111+ #include "ff_host_interface.h"
112+ #endif
113+
110114#define INPCBLBGROUP_SIZMIN 8
111115#define INPCBLBGROUP_SIZMAX 256
112116
@@ -768,6 +772,17 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
768772#ifdef INET6
769773 struct in6_addr * laddr6 , * faddr6 ;
770774#endif
775+ #ifdef FSTACK
776+ u_short rss_first , rss_last , * rss_portrange ;
777+ /* 0:not init, 1:init successed, -1:init failed */
778+ static int rss_tbl_init = 0 ;
779+ int rss_check_flag = lookupflags & INPLOOKUP_LPORT_RSS_CHECK ;
780+ int rss_ret , rss_match = 0 , dorandom ;
781+ struct ifaddr * ifa = NULL ;
782+ struct ifnet * ifp = NULL ;
783+
784+ lookupflags &= ~INPLOOKUP_LPORT_RSS_CHECK ;
785+ #endif
771786
772787 pcbinfo = inp -> inp_pcbinfo ;
773788
@@ -827,20 +842,85 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
827842
828843 tmpinp = NULL ;
829844
845+ #ifdef FSTACK
846+ dorandom = (V_ipport_randomized && first != last ) ? 1 : 0 ;
847+
848+ if (rss_check_flag ) {
849+ if (rss_tbl_init == 0 ) {
850+ rss_ret = ff_rss_tbl_set_portrange (first , last );
851+ rss_tbl_init = (rss_ret < 0 ) ? -1 : 1 ;
852+ }
853+
854+ if (rss_tbl_init == 1 ) {
855+ rss_ret = ff_rss_tbl_get_portrange (faddr .s_addr ,
856+ laddr .s_addr , fport , & rss_first , & rss_last ,
857+ & rss_portrange );
858+ if (rss_ret < 0 ) {
859+ if (rss_ret != - ENOENT )
860+ rss_tbl_init = -1 ;
861+ } else {
862+ /* rss_portrange[0] holds last-selected idx. */
863+ rss_match = 1 ;
864+ count = rss_last - rss_first + 1 ;
865+ if (dorandom )
866+ rss_portrange [0 ] = rss_first +
867+ (arc4random () % count );
868+ }
869+ }
870+
871+ if (!rss_match ) {
872+ /* Locate egress ifp for per-queue ff_rss_check(). */
873+ lsa -> sa_len = sizeof (struct sockaddr_in );
874+ ifa = ifa_ifwithnet (lsa , 0 , RT_ALL_FIBS );
875+ if (ifa == NULL ) {
876+ fsa -> sa_len = sizeof (struct sockaddr_in );
877+ ifa = ifa_ifwithnet (fsa , 0 , RT_ALL_FIBS );
878+ if (ifa == NULL )
879+ return (EADDRNOTAVAIL );
880+ }
881+ ifp = ifa -> ifa_ifp ;
882+ }
883+ }
884+
885+ if (!rss_check_flag || !rss_match ) {
886+ if (dorandom )
887+ * lastport = first + (arc4random () % (last - first ));
888+ count = last - first ;
889+ }
890+ #else
830891 if (V_ipport_randomized )
831892 * lastport = first + (arc4random () % (last - first ));
832893
833894 count = last - first ;
895+ #endif
834896
835897 do {
836898 if (count -- < 0 ) /* completely used? */
837899 return (EADDRNOTAVAIL );
900+ #ifdef FSTACK
901+ if (rss_check_flag && rss_match ) {
902+ rss_portrange [0 ]++ ;
903+ if (rss_portrange [0 ] < rss_first ||
904+ rss_portrange [0 ] > rss_last )
905+ rss_portrange [0 ] = rss_first ;
906+ * lastport = rss_portrange [rss_portrange [0 ]];
907+ } else {
908+ ++ * lastport ;
909+ if (* lastport < first || * lastport > last )
910+ * lastport = first ;
911+ }
912+ #else
838913 ++ * lastport ;
839914 if (* lastport < first || * lastport > last )
840915 * lastport = first ;
916+ #endif
841917 lport = htons (* lastport );
842918
919+ #ifdef FSTACK
920+ if (!rss_check_flag && fsa != NULL ) {
921+ #else
843922 if (fsa != NULL ) {
923+ #endif
844924#ifdef INET
845925 if (lsa -> sa_family == AF_INET ) {
846926 tmpinp = in_pcblookup_hash_locked (pcbinfo ,
@@ -874,8 +954,25 @@ in_pcb_lport_dest(const struct inpcb *inp, struct sockaddr *lsa,
874954 else
875955#endif
876956#ifdef INET
957+ {
877958 tmpinp = in_pcblookup_local (pcbinfo , laddr ,
878959 lport , RT_ALL_FIBS , lookupflags , cred );
960+ #ifdef FSTACK
961+ if (rss_check_flag && !rss_match &&
962+ tmpinp == NULL ) {
963+ /* LOOPBACK does not support RSS. */
964+ if (ifp -> if_softc == NULL &&
965+ (ifp -> if_flags & IFF_LOOPBACK ))
966+ break ;
967+ if (ff_rss_check (ifp -> if_softc ,
968+ faddr .s_addr , laddr .s_addr ,
969+ fport , lport ))
970+ break ;
971+ /* not local queue: keep searching */
972+ tmpinp ++ ;
973+ }
974+ #endif
975+ }
879976#endif
880977 }
881978 } while (tmpinp != NULL );
@@ -1126,9 +1223,16 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr_in *sin, struct ucred *cred)
11261223 faddr = sin -> sin_addr ;
11271224
11281225 if (in_nullhost (inp -> inp_laddr )) {
1129- error = in_pcbladdr (inp , & faddr , & laddr , cred );
1130- if (error )
1131- return (error );
1226+ #ifdef FSTACK
1227+ laddr .s_addr = INADDR_ANY ;
1228+ ff_in_pcbladdr (AF_INET , & faddr , sin -> sin_port , & laddr );
1229+ if (laddr .s_addr == INADDR_ANY )
1230+ #endif
1231+ {
1232+ error = in_pcbladdr (inp , & faddr , & laddr , cred );
1233+ if (error )
1234+ return (error );
1235+ }
11321236 } else
11331237 laddr = inp -> inp_laddr ;
11341238
@@ -1144,7 +1248,11 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr_in *sin, struct ucred *cred)
11441248
11451249 error = in_pcb_lport_dest (inp , (struct sockaddr * )& lsin ,
11461250 & lport , (struct sockaddr * )& fsin , sin -> sin_port , cred ,
1251+ #ifdef FSTACK
1252+ INPLOOKUP_WILDCARD | INPLOOKUP_LPORT_RSS_CHECK );
1253+ #else
11471254 INPLOOKUP_WILDCARD );
1255+ #endif
11481256 if (error )
11491257 return (error );
11501258 } else if (in_pcblookup_hash_locked (inp -> inp_pcbinfo , faddr ,
0 commit comments