Skip to content

Commit 11de5a1

Browse files
committed
Transplant the feature of ff_rss_check table to branch 1.21 that improve the performance of ff_rss_check().
More info see "rss_check" section in config.ini.
1 parent b39850c commit 11de5a1

File tree

9 files changed

+692
-49
lines changed

9 files changed

+692
-49
lines changed

config.ini

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,30 @@ gateway=192.168.1.1
216216
#up_delay=10
217217
#down_delay=50
218218

219+
220+
# ff_rss_check table config section
221+
# To enable or disable static ff_rss_check table.
222+
# If enable it, F-Stack will init the table while the APP is starting.
223+
# Then the APP connect to a sever as client, it will try select a local port from the inited table first.
224+
#
225+
# This feature will greatly improve the performance of selecting local port
226+
# when the F-Stack application actively access remote services as a client and not set keep-alive.
227+
# If the local port is idle, it only needs to be selected once,
228+
# and no longer needs to be selected multiple times (the average number of times is about the total number of processes).
229+
# And the performance of selecting available local ports at a time is also improved compared to ff_rss_check().
230+
# If get rss local port failed, it will be fallback to ff_rss_check().
231+
#
232+
# enable : 0 means disable, 1 means enable. Default 0.
233+
# rss_tbl : Set 4-tuple for ff_rss_check table, Required argumnet.
234+
# <porit_id> <daddr(local addr)> <saddr(remote addr)> <sport(remote port)>
235+
# Separated by space in one 4-tuple, and separated by semicolon between multi 4-tuples.
236+
# The max supported num of 2-tuple with saddr and sport is 4 * 4 = 16.
237+
# The max supported num of daddr with one same saddr and sport is 4.
238+
# So the max combination num of 4-tuple is 16 * 4 = 64, other config will be ignored.
239+
[rss_check]
240+
enable=0
241+
rss_tbl=0 192.168.1.1 192.168.2.1 80;0 192.168.1.1 192.168.2.1 443
242+
219243
# Kni config: if enabled and method=reject,
220244
# all packets that do not belong to the following tcp_port and udp_port
221245
# will transmit to kernel; if method=accept, all packets that belong to
@@ -269,6 +293,8 @@ kern.ipc.maxsockbuf=16777216
269293
net.link.ether.inet.maxhold=5
270294

271295
net.inet.tcp.fast_finwait2_recycle=1
296+
net.inet.tcp.finwait2_timeout=5000
297+
net.inet.tcp.maxtcptw=128
272298
net.inet.tcp.sendspace=16384
273299
net.inet.tcp.recvspace=8192
274300
#net.inet.tcp.nolocaltimewait=1
@@ -287,3 +313,7 @@ net.inet.tcp.delayed_ack=1
287313
net.inet.udp.blackhole=1
288314
net.inet.ip.redirect=0
289315
net.inet.ip.forwarding=0
316+
net.inet.ip.portrange.randomized=1
317+
# Always do random while connect to remote server.
318+
# In some scenarios of F-Stack application, the performance can be improved to a certain extent, ablout 5%.
319+
net.inet.ip.portrange.randomtime=0

freebsd/netinet/in_pcb.c

Lines changed: 196 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ __FBSDID("$FreeBSD$");
106106

107107
#ifdef FSTACK
108108
#include "ff_host_interface.h"
109+
110+
int ff_in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
111+
struct in_addr *faddrp, u_short *fportp, struct ucred *cred, int lookupflags);
109112
#endif
110113

111114
static struct callout ipport_tick_callout;
@@ -500,6 +503,192 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
500503
return (0);
501504
}
502505

506+
#ifdef FSTACK
507+
int
508+
ff_in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
509+
struct in_addr *faddrp, u_short *fportp, struct ucred *cred, int lookupflags)
510+
{
511+
struct inpcbinfo *pcbinfo;
512+
struct inpcb *tmpinp;
513+
unsigned short *lastport;
514+
int count, dorandom, error;
515+
u_short aux, first, last, lport;
516+
#ifdef INET
517+
struct in_addr laddr, faddr;
518+
#endif
519+
u_short rss_first, rss_last, *rss_portrange;
520+
/* 0:not init, 1:init successed, -1:init failed */
521+
static int rss_tbl_init = 0;
522+
int rss_ret, rss_port_idx, rss_match = 0;
523+
struct ifaddr *ifa;
524+
struct ifnet *ifp;
525+
526+
pcbinfo = inp->inp_pcbinfo;
527+
528+
/*
529+
* Because no actual state changes occur here, a global write lock on
530+
* the pcbinfo isn't required.
531+
*/
532+
INP_LOCK_ASSERT(inp);
533+
INP_HASH_LOCK_ASSERT(pcbinfo);
534+
535+
if (inp->inp_flags & INP_HIGHPORT) {
536+
first = V_ipport_hifirstauto; /* sysctl */
537+
last = V_ipport_hilastauto;
538+
lastport = &pcbinfo->ipi_lasthi;
539+
} else if (inp->inp_flags & INP_LOWPORT) {
540+
error = priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT, 0);
541+
if (error)
542+
return (error);
543+
first = V_ipport_lowfirstauto; /* 1023 */
544+
last = V_ipport_lowlastauto; /* 600 */
545+
lastport = &pcbinfo->ipi_lastlow;
546+
} else {
547+
first = V_ipport_firstauto; /* sysctl */
548+
last = V_ipport_lastauto;
549+
lastport = &pcbinfo->ipi_lastport;
550+
}
551+
/*
552+
* For UDP(-Lite), use random port allocation as long as the user
553+
* allows it. For TCP (and as of yet unknown) connections,
554+
* use random port allocation only if the user allows it AND
555+
* ipport_tick() allows it.
556+
*/
557+
if (V_ipport_randomized &&
558+
(!V_ipport_stoprandom || pcbinfo == &V_udbinfo ||
559+
pcbinfo == &V_ulitecbinfo))
560+
dorandom = 1;
561+
else
562+
dorandom = 0;
563+
/*
564+
* It makes no sense to do random port allocation if
565+
* we have the only port available.
566+
*/
567+
if (first == last)
568+
dorandom = 0;
569+
/* Make sure to not include UDP(-Lite) packets in the count. */
570+
if (pcbinfo != &V_udbinfo || pcbinfo != &V_ulitecbinfo)
571+
V_ipport_tcpallocs++;
572+
/*
573+
* Instead of having two loops further down counting up or down
574+
* make sure that first is always <= last and go with only one
575+
* code path implementing all logic.
576+
*/
577+
if (first > last) {
578+
aux = first;
579+
first = last;
580+
last = aux;
581+
}
582+
583+
#ifdef INET
584+
/* Make the compiler happy. */
585+
laddr.s_addr = 0;
586+
if ((inp->inp_vflag & (INP_IPV4|INP_IPV6)) == INP_IPV4) {
587+
KASSERT(laddrp != NULL, ("%s: laddrp NULL for v4 inp %p",
588+
__func__, inp));
589+
laddr = *laddrp;
590+
faddr = *faddrp;
591+
}
592+
#endif
593+
tmpinp = NULL; /* Make compiler happy. */
594+
lport = *lportp;
595+
596+
if (rss_tbl_init == 0) {
597+
rss_ret = ff_rss_tbl_set_portrange(first, last);
598+
if (rss_ret < 0)
599+
rss_tbl_init = -1;
600+
else
601+
rss_tbl_init = 1;
602+
}
603+
604+
if (rss_tbl_init == 1) {
605+
rss_ret = ff_rss_tbl_get_portrange(faddr.s_addr, laddr.s_addr, *fportp,
606+
&rss_first, &rss_last, &rss_portrange);
607+
if (rss_ret < 0) {
608+
if (rss_ret != -ENOENT)
609+
rss_tbl_init = -1;
610+
} else {
611+
/* [0] store last port idx */
612+
rss_match = 1;
613+
count = rss_last - rss_first + 1;
614+
if (dorandom)
615+
rss_portrange[0] = rss_first + (arc4random() % (count));
616+
}
617+
}
618+
619+
if (!rss_match) {
620+
struct sockaddr_in ifp_sin;
621+
bzero(&ifp_sin, sizeof(ifp_sin));
622+
ifp_sin.sin_addr.s_addr = laddr.s_addr;
623+
ifp_sin.sin_family = AF_INET;
624+
ifp_sin.sin_len = sizeof(ifp_sin);
625+
ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS);
626+
if (ifa == NULL) {
627+
628+
ifp_sin.sin_addr.s_addr = faddr.s_addr;
629+
ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS);
630+
if ( ifa == NULL )
631+
return (EADDRNOTAVAIL);
632+
}
633+
ifp = ifa->ifa_ifp;
634+
635+
if (dorandom)
636+
*lastport = first + (arc4random() % (last - first));
637+
638+
count = last - first;
639+
}
640+
641+
do {
642+
if (count-- < 0) /* completely used? */
643+
return (EADDRNOTAVAIL);
644+
if (rss_match) {
645+
rss_portrange[0]++;
646+
if (rss_portrange[0] < rss_first || rss_portrange[0] > rss_last)
647+
rss_portrange[0] = rss_first;
648+
*lastport = rss_portrange[rss_portrange[0]];
649+
} else {
650+
++*lastport;
651+
if (*lastport < first || *lastport > last)
652+
*lastport = first;
653+
}
654+
lport = htons(*lastport);
655+
656+
#ifdef INET6
657+
if ((inp->inp_vflag & INP_IPV6) != 0)
658+
tmpinp = in6_pcblookup_local(pcbinfo,
659+
&inp->in6p_laddr, lport, lookupflags, cred);
660+
#endif
661+
#if defined(INET) && defined(INET6)
662+
else
663+
#endif
664+
#ifdef INET
665+
{
666+
tmpinp = in_pcblookup_local(pcbinfo, laddr,
667+
lport, lookupflags, cred);
668+
if (!rss_match && tmpinp == NULL) {
669+
int rss;
670+
/* Note:
671+
* LOOPBACK not support rss.
672+
*/
673+
if ((ifp->if_softc == NULL) && (ifp->if_flags & IFF_LOOPBACK))
674+
break;
675+
rss = ff_rss_check(ifp->if_softc, faddr.s_addr, laddr.s_addr,
676+
*fportp, lport);
677+
if (rss)
678+
break;
679+
else
680+
tmpinp++; /* Set not NULL to find another lport */
681+
}
682+
}
683+
#endif
684+
} while (tmpinp != NULL);
685+
686+
*lportp = lport;
687+
688+
return (0);
689+
}
690+
#endif
691+
503692
/*
504693
* Return cached socket options.
505694
*/
@@ -1118,61 +1307,19 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
11181307
*oinpp = oinp;
11191308
return (EADDRINUSE);
11201309
}
1121-
#ifndef FSTACK
1310+
11221311
if (lport == 0) {
1312+
#ifndef FSTACK
11231313
error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport,
11241314
cred);
1315+
#else
1316+
error = ff_in_pcb_lport(inp, &laddr, &lport, &faddr, &fport,
1317+
cred, INPLOOKUP_WILDCARD);
1318+
#endif
11251319
if (error)
11261320
return (error);
11271321
}
1128-
#else
1129-
if (lport == 0)
1130-
{
1131-
struct ifaddr *ifa;
1132-
struct ifnet *ifp;
1133-
struct sockaddr_in ifp_sin;
1134-
unsigned loop_count = 0;
1135-
bzero(&ifp_sin, sizeof(ifp_sin));
1136-
ifp_sin.sin_addr.s_addr = laddr.s_addr;
1137-
ifp_sin.sin_family = AF_INET;
1138-
ifp_sin.sin_len = sizeof(ifp_sin);
1139-
ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS);
1140-
if (ifa == NULL) {
1141-
ifp_sin.sin_addr.s_addr = faddr.s_addr;
1142-
ifa = ifa_ifwithnet((struct sockaddr *)&ifp_sin, 0, RT_ALL_FIBS);
1143-
if ( ifa == NULL )
1144-
return (EADDRNOTAVAIL);
1145-
}
1146-
ifp = ifa->ifa_ifp;
1147-
while (lport == 0) {
1148-
int rss;
1149-
error = in_pcb_lport(inp, &laddr, &lport, cred, INPLOOKUP_WILDCARD);
1150-
if (error)
1151-
return (error);
1152-
/* Note:
1153-
* if ifp->if_softc is NULL, such as laddr config in lo.
1154-
* just return. but maybe it can't receive response to this worker.
1155-
*/
1156-
if (!ifp->if_softc) {
1157-
break;
1158-
}
1159-
rss = ff_rss_check(ifp->if_softc, faddr.s_addr, laddr.s_addr,
1160-
fport, lport);
1161-
if (rss) {
1162-
break;
1163-
}
1164-
lport = 0;
1165-
/* Note:
1166-
* if all ports are completely used, just return.
1167-
* this ugly code is not a correct way, it just lets loop quit.
1168-
* we will fix it as soon as possible.
1169-
*/
1170-
if (++loop_count >= 65535) {
1171-
return (EADDRNOTAVAIL);
1172-
}
1173-
}
1174-
}
1175-
#endif
1322+
11761323
*laddrp = laddr.s_addr;
11771324
*lportp = lport;
11781325
*faddrp = faddr.s_addr;

lib/ff_api.symlist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ ff_zc_mbuf_write
5959
ff_zc_mbuf_read
6060
ff_get_traffic
6161
ff_dpdk_raw_packet_send
62+
ff_rss_tbl_init
63+
ff_veth_get_softc
64+
ff_veth_free_softc
6265
ff_openlog_stream
6366
ff_log_set_global_level
6467
ff_log_set_level

0 commit comments

Comments
 (0)