@@ -700,6 +700,17 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
700700#ifdef INET6
701701 struct in6_addr * laddr6 = NULL , * faddr6 = NULL ;
702702#endif
703+ #ifdef FSTACK
704+ u_short rss_first , rss_last , * rss_portrange ;
705+ /* 0:not init, 1:init successed, -1:init failed */
706+ static int rss_tbl_init = 0 ;
707+ int rss_check_flag = lookupflags & INPLOOKUP_LPORT_RSS_CHECK ;
708+ int rss_ret , rss_port_idx , rss_match = 0 ;
709+ struct ifaddr * ifa ;
710+ struct ifnet * ifp ;
711+
712+ lookupflags = lookupflags & (~INPLOOKUP_LPORT_RSS_CHECK );
713+ #endif
703714
704715 pcbinfo = inp -> inp_pcbinfo ;
705716
@@ -780,20 +791,81 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
780791 tmpinp = NULL ;
781792 lport = * lportp ;
782793
794+ #ifdef FSTACK
795+ if (rss_check_flag ) {
796+ if (rss_tbl_init == 0 ) {
797+ rss_ret = ff_rss_tbl_set_portrange (first , last );
798+ if (rss_ret < 0 )
799+ rss_tbl_init = -1 ;
800+ else
801+ rss_tbl_init = 1 ;
802+ }
803+
804+ if (rss_tbl_init == 1 ) {
805+ rss_ret = ff_rss_tbl_get_portrange (faddr .s_addr , laddr .s_addr , fport ,
806+ & rss_first , & rss_last , & rss_portrange );
807+ if (rss_ret < 0 ) {
808+ if (rss_ret != - ENOENT )
809+ rss_tbl_init = -1 ;
810+ } else {
811+ /* [0] store last port idx */
812+ rss_match = 1 ;
813+ count = rss_last - rss_first + 1 ;
814+ if (dorandom )
815+ rss_portrange [0 ] = rss_first + (arc4random () % (count ));
816+ }
817+ }
818+
819+ if (!rss_match ) {
820+ lsa -> sa_len = sizeof (struct sockaddr_in );
821+ ifa = ifa_ifwithnet (lsa , 0 , RT_ALL_FIBS );
822+ if (ifa == NULL ) {
823+ fsa -> sa_len = sizeof (struct sockaddr_in );
824+ ifa = ifa_ifwithnet (fsa , 0 , RT_ALL_FIBS );
825+ if ( ifa == NULL )
826+ return (EADDRNOTAVAIL );
827+ }
828+ ifp = ifa -> ifa_ifp ;
829+ }
830+ }
831+
832+ if (!rss_check_flag || !rss_match ) {
833+ #endif
783834 if (dorandom )
784835 * lastport = first + (arc4random () % (last - first ));
785836
786837 count = last - first ;
838+ #ifdef FSTACK
839+ }
840+ #endif
787841
788842 do {
789843 if (count -- < 0 ) /* completely used? */
790844 return (EADDRNOTAVAIL );
845+ #ifdef FSTACK
846+ if (rss_check_flag && rss_match ) {
847+ rss_portrange [0 ]++ ;
848+ if (rss_portrange [0 ] < rss_first || rss_portrange [0 ] > rss_last )
849+ rss_portrange [0 ] = rss_first ;
850+ * lastport = rss_portrange [rss_portrange [0 ]];
851+ }
852+
853+ if (!rss_check_flag || !rss_match ) {
854+ #endif
791855 ++ * lastport ;
792856 if (* lastport < first || * lastport > last )
793857 * lastport = first ;
858+ #ifdef FSTACK
859+ }
860+ #endif
794861 lport = htons (* lastport );
795862
796- if (fsa != NULL ) {
863+ #ifdef FSTACK
864+ if (!rss_check_flag && fsa != NULL )
865+ #else
866+ if (fsa != NULL )
867+ #endif
868+ {
797869#ifdef INET
798870 if (lsa -> sa_family == AF_INET ) {
799871 tmpinp = in_pcblookup_hash_locked (pcbinfo ,
@@ -818,8 +890,26 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
818890 else
819891#endif
820892#ifdef INET
893+ {
821894 tmpinp = in_pcblookup_local (pcbinfo , laddr ,
822895 lport , lookupflags , cred );
896+ #ifdef FSTACK
897+ if (rss_check_flag && !rss_match && tmpinp == NULL ) {
898+ int rss ;
899+ /* Note:
900+ * LOOPBACK not support rss.
901+ */
902+ if ((ifp -> if_softc == NULL ) && (ifp -> if_flags & IFF_LOOPBACK ))
903+ break ;
904+ rss = ff_rss_check (ifp -> if_softc , faddr .s_addr , laddr .s_addr ,
905+ fport , lport );
906+ if (rss )
907+ break ;
908+ else
909+ tmpinp ++ ; /* Set not NULL to find another lport */
910+ }
911+ #endif
912+ }
823913#endif
824914 }
825915 } while (tmpinp != NULL );
@@ -1483,9 +1573,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
14831573 return (EADDRINUSE );
14841574 }
14851575 } else {
1486- #ifndef FSTACK
14871576 struct sockaddr_in lsin , fsin ;
1488-
14891577 bzero (& lsin , sizeof (lsin ));
14901578 bzero (& fsin , sizeof (fsin ));
14911579 lsin .sin_family = AF_INET ;
@@ -1494,52 +1582,13 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
14941582 fsin .sin_addr = faddr ;
14951583 error = in_pcb_lport_dest (inp , (struct sockaddr * ) & lsin ,
14961584 & lport , (struct sockaddr * )& fsin , fport , cred ,
1585+ #ifndef FSTACK
14971586 INPLOOKUP_WILDCARD );
1498- if (error )
1499- return (error );
15001587#else
1501- struct ifaddr * ifa ;
1502- struct ifnet * ifp ;
1503- struct sockaddr_in ifp_sin ;
1504- unsigned loop_count = 0 ;
1505- bzero (& ifp_sin , sizeof (ifp_sin ));
1506- ifp_sin .sin_addr .s_addr = laddr .s_addr ;
1507- ifp_sin .sin_family = AF_INET ;
1508- ifp_sin .sin_len = sizeof (ifp_sin );
1509- ifa = ifa_ifwithnet ((struct sockaddr * )& ifp_sin , 0 , RT_ALL_FIBS );
1510- if (ifa == NULL ) {
1511- ifp_sin .sin_addr .s_addr = faddr .s_addr ;
1512- ifa = ifa_ifwithnet ((struct sockaddr * )& ifp_sin , 0 , RT_ALL_FIBS );
1513- if ( ifa == NULL )
1514- return (EADDRNOTAVAIL );
1515- }
1516- ifp = ifa -> ifa_ifp ;
1517- while (lport == 0 ) {
1518- int rss ;
1519- error = in_pcb_lport (inp , & laddr , & lport , cred , INPLOOKUP_WILDCARD );
1520- if (error )
1521- return (error );
1522- /* Note:
1523- * LOOPBACK not support rss.
1524- */
1525- if ((ifp -> if_softc == NULL ) && (ifp -> if_flags & IFF_LOOPBACK ))
1526- break ;
1527- rss = ff_rss_check (ifp -> if_softc , faddr .s_addr , laddr .s_addr ,
1528- fport , lport );
1529- if (rss ) {
1530- break ;
1531- }
1532- lport = 0 ;
1533- /* Note:
1534- * if all ports are completely used, just return.
1535- * this ugly code is not a correct way, it just lets loop quit.
1536- * we will fix it as soon as possible.
1537- */
1538- if (++ loop_count >= 65535 ) {
1539- return (EADDRNOTAVAIL );
1540- }
1541- }
1588+ INPLOOKUP_WILDCARD | INPLOOKUP_LPORT_RSS_CHECK );
15421589#endif
1590+ if (error )
1591+ return (error );
15431592 }
15441593 * laddrp = laddr .s_addr ;
15451594 * lportp = lport ;
0 commit comments