aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2021-10-26 03:53:07 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2021-10-27 15:22:00 +0000
commitf581a26e46b896657fd502672c134da115057839 (patch)
tree25f3b2be54f3015a2c40b54c24f3741f8914e67c /sys
parentde156263a598a0277b7bbc13ef8bdc6f4541b604 (diff)
downloadsrc-f581a26e46b896657fd502672c134da115057839.tar.gz
src-f581a26e46b896657fd502672c134da115057839.zip
Factor out tcp6_use_min_mtu() to handle IPV6_USE_MIN_MTU by TCP.
Pass control for IP/IP6 level options from generic tcp_ctloutput_set() down to per-stack ctloutput. Call tcp6_use_min_mtu() from tcp stack tcp_default_ctloutput(). Reviewed by: rrs Differential Revision: https://reviews.freebsd.org/D32655
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/tcp_stacks/bbr.c6
-rw-r--r--sys/netinet/tcp_stacks/rack.c19
-rw-r--r--sys/netinet/tcp_subr.c35
-rw-r--r--sys/netinet/tcp_usrreq.c60
-rw-r--r--sys/netinet/tcp_var.h1
5 files changed, 84 insertions, 37 deletions
diff --git a/sys/netinet/tcp_stacks/bbr.c b/sys/netinet/tcp_stacks/bbr.c
index 3c4cf0f54d97..41f441da99a1 100644
--- a/sys/netinet/tcp_stacks/bbr.c
+++ b/sys/netinet/tcp_stacks/bbr.c
@@ -14253,6 +14253,12 @@ bbr_set_sockopt(struct socket *so, struct sockopt *sopt,
struct epoch_tracker et;
int32_t error = 0, optval;
+ switch (sopt->sopt_level) {
+ case IPPROTO_IPV6:
+ case IPPROTO_IP:
+ return (tcp_default_ctloutput(so, sopt, inp, tp));
+ }
+
switch (sopt->sopt_name) {
case TCP_RACK_PACE_MAX_SEG:
case TCP_RACK_MIN_TO:
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index eee7db6e7a4c..3e3997f8e18e 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -20248,6 +20248,25 @@ rack_set_sockopt(struct socket *so, struct sockopt *sopt,
uint64_t loptval;
int32_t error = 0, optval;
+ switch (sopt->sopt_level) {
+#ifdef INET6
+ case IPPROTO_IPV6:
+ MPASS(inp->inp_vflag & INP_IPV6PROTO);
+ switch (sopt->sopt_name) {
+ case IPV6_USE_MIN_MTU:
+ tcp6_use_min_mtu(tp);
+ /* FALLTHROUGH */
+ }
+ INP_WUNLOCK(inp);
+ return (0);
+#endif
+#ifdef INET
+ case IPPROTO_IP:
+ INP_WUNLOCK(inp);
+ return (0);
+#endif
+ }
+
switch (sopt->sopt_name) {
case TCP_RACK_TLP_REDUCE: /* URL:tlp_reduce */
/* Pacing related ones */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 2752773a95fc..e12eb5682c14 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -3559,6 +3559,41 @@ tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap)
return (maxmtu);
}
+
+/*
+ * Handle setsockopt(IPV6_USE_MIN_MTU) by a TCP stack.
+ *
+ * XXXGL: we are updating inpcb here with INC_IPV6MINMTU flag.
+ * The right place to do that is ip6_setpktopt() that has just been
+ * executed. By the way it just filled ip6po_minmtu for us.
+ */
+void
+tcp6_use_min_mtu(struct tcpcb *tp)
+{
+ struct inpcb *inp = tp->t_inpcb;
+
+ INP_WLOCK_ASSERT(inp);
+ /*
+ * In case of the IPV6_USE_MIN_MTU socket
+ * option, the INC_IPV6MINMTU flag to announce
+ * a corresponding MSS during the initial
+ * handshake. If the TCP connection is not in
+ * the front states, just reduce the MSS being
+ * used. This avoids the sending of TCP
+ * segments which will be fragmented at the
+ * IPv6 layer.
+ */
+ inp->inp_inc.inc_flags |= INC_IPV6MINMTU;
+ if ((tp->t_state >= TCPS_SYN_SENT) &&
+ (inp->inp_inc.inc_flags & INC_ISIPV6)) {
+ struct ip6_pktopts *opt;
+
+ opt = inp->in6p_outputopts;
+ if (opt != NULL && opt->ip6po_minmtu == IP6PO_MINMTU_ALL &&
+ tp->t_maxseg > TCP6_MSS)
+ tp->t_maxseg = TCP6_MSS;
+ }
+}
#endif /* INET6 */
/*
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index b6e345bd454c..7e703af5aa67 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1763,43 +1763,8 @@ tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt)
/* Notify tcp stacks that care (e.g. RACK). */
break;
case IPV6_USE_MIN_MTU:
- /*
- * XXXGL: this handling should belong to
- * stack specific tfb_tcp_ctloutput, we
- * should just break here.
- *
- * In case of the IPV6_USE_MIN_MTU socket
- * option, the INC_IPV6MINMTU flag to announce
- * a corresponding MSS during the initial
- * handshake. If the TCP connection is not in
- * the front states, just reduce the MSS being
- * used. This avoids the sending of TCP
- * segments which will be fragmented at the
- * IPv6 layer.
- */
- INP_WLOCK(inp);
- if ((inp->inp_flags &
- (INP_TIMEWAIT | INP_DROPPED))) {
- INP_WUNLOCK(inp);
- return (ECONNRESET);
- }
- inp->inp_inc.inc_flags |= INC_IPV6MINMTU;
- tp = intotcpcb(inp);
- if ((tp->t_state >= TCPS_SYN_SENT) &&
- (inp->inp_inc.inc_flags & INC_ISIPV6)) {
- struct ip6_pktopts *opt;
-
- opt = inp->in6p_outputopts;
- if ((opt != NULL) &&
- (opt->ip6po_minmtu ==
- IP6PO_MINMTU_ALL)) {
- if (tp->t_maxseg > TCP6_MSS) {
- tp->t_maxseg = TCP6_MSS;
- }
- }
- }
- INP_WUNLOCK(inp);
- /* FALLTHROUGH */
+ /* Update t_maxseg accordingly. */
+ break;
default:
return (error);
}
@@ -2058,6 +2023,27 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
#endif
size_t len;
+ INP_WLOCK_ASSERT(inp);
+
+ switch (sopt->sopt_level) {
+#ifdef INET6
+ case IPPROTO_IPV6:
+ MPASS(inp->inp_vflag & INP_IPV6PROTO);
+ switch (sopt->sopt_name) {
+ case IPV6_USE_MIN_MTU:
+ tcp6_use_min_mtu(tp);
+ /* FALLTHROUGH */
+ }
+ INP_WUNLOCK(inp);
+ return (0);
+#endif
+#ifdef INET
+ case IPPROTO_IP:
+ INP_WUNLOCK(inp);
+ return (0);
+#endif
+ }
+
/*
* For TCP_CCALGOOPT forward the control to CC module, for both
* SOPT_SET and SOPT_GET.
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 2775fb392a1a..1511da3c70fd 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1053,6 +1053,7 @@ extern uint32_t tcp_ack_war_cnt;
uint32_t tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *);
uint32_t tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *);
+void tcp6_use_min_mtu(struct tcpcb *);
u_int tcp_maxseg(const struct tcpcb *);
u_int tcp_fixed_maxseg(const struct tcpcb *);
void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,