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 */
 };
 
 /*

Reply via email to