git: 5d3bf5b1d27f - main - rack: Update the fast send block on setsockopt(2)

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Wed, 27 Oct 2021 15:23:00 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=5d3bf5b1d27f4b2bd85f40e26987af83353616f0

commit 5d3bf5b1d27f4b2bd85f40e26987af83353616f0
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2021-10-26 03:54:26 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2021-10-27 15:22:00 +0000

    rack: Update the fast send block on setsockopt(2)
    
    Rack caches TCP/IP header for fast send, so it doesn't call
    tcpip_fillheaders().  After certain socket option changes,
    namely IPV6_TCLASS, IP_TOS and IP_TTL it needs to update
    its fast block to be in sync with the inpcb.
    
    Reviewed by:            rrs
    Differential Revision:  https://reviews.freebsd.org/D32655
---
 sys/netinet/tcp_stacks/rack.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index 3e3997f8e18e..a92e43205f09 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -20245,6 +20245,12 @@ static int
 rack_set_sockopt(struct socket *so, struct sockopt *sopt,
     struct inpcb *inp, struct tcpcb *tp, struct tcp_rack *rack)
 {
+#ifdef INET6
+	struct ip6_hdr *ip6 = (struct ip6_hdr *)rack->r_ctl.fsb.tcp_ip_hdr;
+#endif
+#ifdef INET
+	struct ip *ip = (struct ip *)rack->r_ctl.fsb.tcp_ip_hdr;
+#endif
 	uint64_t loptval;
 	int32_t error = 0, optval;
 
@@ -20255,13 +20261,34 @@ rack_set_sockopt(struct socket *so, struct sockopt *sopt,
 		switch (sopt->sopt_name) {
 		case IPV6_USE_MIN_MTU:
 			tcp6_use_min_mtu(tp);
-			/* FALLTHROUGH */
+			break;
+		case IPV6_TCLASS:
+			/*
+			 * The DSCP codepoint has changed, update the fsb.
+			 */
+			ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
+			    (rack->rc_inp->inp_flow & IPV6_FLOWINFO_MASK);
+			break;
 		}
 		INP_WUNLOCK(inp);
 		return (0);
 #endif
 #ifdef INET
 	case IPPROTO_IP:
+		switch (sopt->sopt_name) {
+		case IP_TOS:
+			/*
+			 * The DSCP codepoint has changed, update the fsb.
+			 */
+			ip->ip_tos = rack->rc_inp->inp_ip_tos;
+			break;
+		case IP_TTL:
+			/*
+			 * The TTL has changed, update the fsb.
+			 */
+			ip->ip_ttl = rack->rc_inp->inp_ip_ttl;
+			break;
+		}
 		INP_WUNLOCK(inp);
 		return (0);
 #endif