The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=73fe85e486d297c9c976095854c1c84007e543f0
commit 73fe85e486d297c9c976095854c1c84007e543f0 Author: Gleb Smirnoff <[email protected]> AuthorDate: 2025-12-03 23:15:34 +0000 Commit: Gleb Smirnoff <[email protected]> CommitDate: 2025-12-03 23:19:44 +0000 tcp: store flowid info in syncache Now retransmissions by syncache would use correct flowid, same as synchronous responds. Reviewed by: tuexen, gallatin Differential Revision: https://reviews.freebsd.org/D51792 --- sys/netinet/tcp_input.c | 2 +- sys/netinet/tcp_syncache.c | 101 +++++++++++++++++++++++++++++---------------- sys/netinet/tcp_syncache.h | 8 ++-- 3 files changed, 70 insertions(+), 41 deletions(-) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 85ab26351f6b..9014dd690764 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1171,7 +1171,7 @@ tfo_socket_result: * causes. */ if (thflags & TH_RST) { - syncache_chkrst(&inc, th, m, port); + syncache_chkrst(&inc, th, port); goto dropunlock; } /* diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 056542bc43d6..eb473dac4dfc 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -35,6 +35,7 @@ #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_rss.h" #include <sys/param.h> #include <sys/systm.h> @@ -120,8 +121,8 @@ SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW, static void syncache_drop(struct syncache *, struct syncache_head *); static void syncache_free(struct syncache *); static void syncache_insert(struct syncache *, struct syncache_head *); -static int syncache_respond(struct syncache *, const struct mbuf *, int); -static void syncache_send_challenge_ack(struct syncache *, struct mbuf *); +static int syncache_respond(struct syncache *, int); +static void syncache_send_challenge_ack(struct syncache *); static struct socket *syncache_socket(struct syncache *, struct socket *, struct mbuf *m); static void syncache_timeout(struct syncache *sc, struct syncache_head *sch, @@ -528,7 +529,7 @@ syncache_timer(void *xsch) } NET_EPOCH_ENTER(et); - if (syncache_respond(sc, NULL, TH_SYN|TH_ACK) == 0) { + if (syncache_respond(sc, TH_SYN|TH_ACK) == 0) { syncache_timeout(sc, sch, 0); TCPSTAT_INC(tcps_sndacks); TCPSTAT_INC(tcps_sndtotal); @@ -611,8 +612,7 @@ syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp) * If required send a challenge ACK. */ void -syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th, struct mbuf *m, - uint16_t port) +syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th, uint16_t port) { struct syncache *sc; struct syncache_head *sch; @@ -698,7 +698,7 @@ syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th, struct mbuf *m, "sending challenge ACK\n", s, __func__, th->th_seq, sc->sc_irs + 1, sc->sc_wnd); - syncache_send_challenge_ack(sc, m); + syncache_send_challenge_ack(sc); } } else { if ((s = tcp_log_addrs(inc, th, NULL, NULL))) @@ -807,19 +807,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) #ifdef INET6 } #endif - - /* - * If there's an mbuf and it has a flowid, then let's initialise the - * inp with that particular flowid. - */ - if (m != NULL && M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { - inp->inp_flowid = m->m_pkthdr.flowid; - inp->inp_flowtype = M_HASHTYPE_GET(m); -#ifdef NUMA - inp->inp_numa_domain = m->m_pkthdr.numa_domain; -#endif - } - inp->inp_lport = sc->sc_inc.inc_lport; #ifdef INET6 if (inp->inp_vflag & INP_IPV6PROTO) { @@ -890,6 +877,38 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) if (ipsec_copy_pcbpolicy(sotoinpcb(lso), inp) != 0) printf("syncache_socket: could not copy policy\n"); #endif + if (sc->sc_flowtype != M_HASHTYPE_NONE) { + inp->inp_flowid = sc->sc_flowid; + inp->inp_flowtype = sc->sc_flowtype; +#ifdef RSS + } else { + /* assign flowid by software RSS hash */ +#ifdef INET6 + if (sc->sc_inc.inc_flags & INC_ISIPV6) { + rss_proto_software_hash_v6(&inp->in6p_faddr, + &inp->in6p_laddr, + inp->inp_fport, + inp->inp_lport, + IPPROTO_TCP, + &inp->inp_flowid, + &inp->inp_flowtype); + } else +#endif /* INET6 */ + { + rss_proto_software_hash_v4(inp->inp_faddr, + inp->inp_laddr, + inp->inp_fport, + inp->inp_lport, + IPPROTO_TCP, + &inp->inp_flowid, + &inp->inp_flowtype); + } +#endif /* RSS */ + } +#ifdef NUMA + inp->inp_numa_domain = sc->sc_numa_domain; +#endif + tp->t_state = TCPS_SYN_RECEIVED; tp->iss = sc->sc_iss; tp->irs = sc->sc_irs; @@ -1144,6 +1163,13 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, return (-1); /* Do not send RST */ } #endif /* TCP_SIGNATURE */ + if (m != NULL && M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { + sc->sc_flowid = m->m_pkthdr.flowid; + sc->sc_flowtype = M_HASHTYPE_GET(m); + } +#ifdef NUMA + sc->sc_numa_domain = m ? m->m_pkthdr.numa_domain : M_NODOM; +#endif TCPSTATES_INC(TCPS_SYN_RECEIVED); } else { if (sc->sc_port != port) { @@ -1262,7 +1288,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u, " "sending challenge ACK\n", s, __func__, th->th_seq, sc->sc_irs + 1); - syncache_send_challenge_ack(sc, m); + syncache_send_challenge_ack(sc); SCH_UNLOCK(sch); free(s, M_TCPLOG); return (-1); /* Do not send RST */ @@ -1559,7 +1585,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, s, __func__); free(s, M_TCPLOG); } - if (syncache_respond(sc, m, TH_SYN|TH_ACK) == 0) { + if (syncache_respond(sc, TH_SYN|TH_ACK) == 0) { sc->sc_rxmits = 0; syncache_timeout(sc, sch, 1); TCPSTAT_INC(tcps_sndacks); @@ -1734,6 +1760,13 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, sc->sc_flowlabel = ip6_randomflowlabel(); sc->sc_flowlabel = htonl(sc->sc_flowlabel) & IPV6_FLOWLABEL_MASK; } +#endif + if (m != NULL && M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { + sc->sc_flowid = m->m_pkthdr.flowid; + sc->sc_flowtype = M_HASHTYPE_GET(m); + } +#ifdef NUMA + sc->sc_numa_domain = m ? m->m_pkthdr.numa_domain : M_NODOM; #endif if (locked) SCH_UNLOCK(sch); @@ -1748,7 +1781,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, /* * Do a standard 3-way handshake. */ - if (syncache_respond(sc, m, TH_SYN|TH_ACK) == 0) { + if (syncache_respond(sc, TH_SYN|TH_ACK) == 0) { if (sc != &scs) syncache_insert(sc, sch); /* locks and unlocks sch */ TCPSTAT_INC(tcps_sndacks); @@ -1791,11 +1824,11 @@ tfo_expanded: } /* - * Send SYN|ACK or ACK to the peer. Either in response to a peer's segment, - * i.e. m0 != NULL, or upon 3WHS ACK timeout, i.e. m0 == NULL. + * Send SYN|ACK or ACK to the peer. Either in response to a peer's segment + * or upon 3WHS ACK timeout. */ static int -syncache_respond(struct syncache *sc, const struct mbuf *m0, int flags) +syncache_respond(struct syncache *sc, int flags) { struct ip *ip = NULL; struct mbuf *m; @@ -1985,15 +2018,11 @@ syncache_respond(struct syncache *sc, const struct mbuf *m0, int flags) udp->uh_ulen = htons(ulen); } M_SETFIB(m, sc->sc_inc.inc_fibnum); - /* - * If we have peer's SYN and it has a flowid, then let's assign it to - * our SYN|ACK. ip6_output() and ip_output() will not assign flowid - * to SYN|ACK due to lack of inp here. - */ - if (m0 != NULL && M_HASHTYPE_GET(m0) != M_HASHTYPE_NONE) { - m->m_pkthdr.flowid = m0->m_pkthdr.flowid; - M_HASHTYPE_SET(m, M_HASHTYPE_GET(m0)); - } + m->m_pkthdr.flowid = sc->sc_flowid; + M_HASHTYPE_SET(m, sc->sc_flowtype); +#ifdef NUMA + m->m_pkthdr.numa_domain = sc->sc_numa_domain; +#endif #ifdef INET6 if (sc->sc_inc.inc_flags & INC_ISIPV6) { if (sc->sc_port) { @@ -2056,11 +2085,11 @@ syncache_respond(struct syncache *sc, const struct mbuf *m0, int flags) } static void -syncache_send_challenge_ack(struct syncache *sc, struct mbuf *m) +syncache_send_challenge_ack(struct syncache *sc) { if (tcp_challenge_ack_check(&sc->sc_challenge_ack_end, &sc->sc_challenge_ack_cnt)) { - if (syncache_respond(sc, m, TH_ACK) == 0) { + if (syncache_respond(sc, TH_ACK) == 0) { TCPSTAT_INC(tcps_sndacks); TCPSTAT_INC(tcps_sndtotal); } diff --git a/sys/netinet/tcp_syncache.h b/sys/netinet/tcp_syncache.h index c916b4de6ae0..ce5ad666b115 100644 --- a/sys/netinet/tcp_syncache.h +++ b/sys/netinet/tcp_syncache.h @@ -43,8 +43,7 @@ int syncache_expand(struct in_conninfo *, struct tcpopt *, struct socket * syncache_add(struct in_conninfo *, struct tcpopt *, struct tcphdr *, struct inpcb *, struct socket *, struct mbuf *, void *, void *, uint8_t, uint16_t); -void syncache_chkrst(struct in_conninfo *, struct tcphdr *, struct mbuf *, - uint16_t); +void syncache_chkrst(struct in_conninfo *, struct tcphdr *, uint16_t); int syncache_pcblist(struct sysctl_req *); struct syncache { @@ -65,6 +64,7 @@ struct syncache { u_int8_t sc_ip_tos; /* TOS / Traffic Class */ u_int8_t sc_requested_s_scale:4, sc_requested_r_scale:4; + uint8_t sc_numa_domain; u_int16_t sc_flags; u_int32_t sc_challenge_ack_cnt; /* chall. ACKs sent in epoch */ sbintime_t sc_challenge_ack_end; /* End of chall. ack epoch */ @@ -75,8 +75,8 @@ struct syncache { struct label *sc_label; /* MAC label reference */ struct ucred *sc_cred; /* cred cache for jail checks */ void *sc_tfo_cookie; /* for TCP Fast Open response */ - void *sc_pspare; /* TCP_SIGNATURE */ - u_int32_t sc_spare[2]; /* UTO */ + uint32_t sc_flowtype; /* flowid from SYN packet .. */ + uint32_t sc_flowid; /* .. or calculated by RSS */ }; /*
