diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2021-10-26 03:54:26 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2021-10-27 15:22:00 +0000 |
commit | 5d3bf5b1d27f4b2bd85f40e26987af83353616f0 (patch) | |
tree | 8d613e72ee023ab5af3f2ea69fa089efa3ac5ecf | |
parent | f581a26e46b896657fd502672c134da115057839 (diff) |
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
-rw-r--r-- | sys/netinet/tcp_stacks/rack.c | 29 |
1 files changed, 28 insertions, 1 deletions
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 |