aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2021-10-26 03:54:26 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2021-10-27 15:22:00 +0000
commit5d3bf5b1d27f4b2bd85f40e26987af83353616f0 (patch)
tree8d613e72ee023ab5af3f2ea69fa089efa3ac5ecf
parentf581a26e46b896657fd502672c134da115057839 (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.c29
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