diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2021-10-26 03:53:07 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2021-10-27 15:22:00 +0000 |
commit | f581a26e46b896657fd502672c134da115057839 (patch) | |
tree | 25f3b2be54f3015a2c40b54c24f3741f8914e67c /sys | |
parent | de156263a598a0277b7bbc13ef8bdc6f4541b604 (diff) | |
download | src-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.c | 6 | ||||
-rw-r--r-- | sys/netinet/tcp_stacks/rack.c | 19 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 35 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 60 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 1 |
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 *, |