git: 73fe85e486d2 - main - tcp: store flowid info in syncache
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 03 Dec 2025 23:19:58 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=73fe85e486d297c9c976095854c1c84007e543f0
commit 73fe85e486d297c9c976095854c1c84007e543f0
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-12-03 23:15:34 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
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 */
};
/*