The branch main has been updated by glebius:

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

commit f581a26e46b896657fd502672c134da115057839
Author:     Gleb Smirnoff <[email protected]>
AuthorDate: 2021-10-26 03:53:07 +0000
Commit:     Gleb Smirnoff <[email protected]>
CommitDate: 2021-10-27 15:22:00 +0000

    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
---
 sys/netinet/tcp_stacks/bbr.c  |  6 +++++
 sys/netinet/tcp_stacks/rack.c | 19 ++++++++++++++
 sys/netinet/tcp_subr.c        | 35 +++++++++++++++++++++++++
 sys/netinet/tcp_usrreq.c      | 60 +++++++++++++++++--------------------------
 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 *,

Reply via email to