Author: tuexen
Date: Sat Apr  7 20:08:17 2018
New Revision: 332222
URL: https://svnweb.freebsd.org/changeset/base/332222

Log:
  MFC r325370:
  
  Allow the setting of the MTU for future paths using an SCTP socket option.
  This functionality was missing.

Modified:
  stable/11/sys/netinet/sctp_output.c
  stable/11/sys/netinet/sctp_pcb.c
  stable/11/sys/netinet/sctp_pcb.h
  stable/11/sys/netinet/sctp_structs.h
  stable/11/sys/netinet/sctp_usrreq.c
  stable/11/sys/netinet/sctputil.c
  stable/11/sys/netinet6/sctp6_usrreq.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/sctp_output.c
==============================================================================
--- stable/11/sys/netinet/sctp_output.c Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet/sctp_output.c Sat Apr  7 20:08:17 2018        
(r332222)
@@ -4273,12 +4273,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
                                /* free tempy routes */
                                RO_RTFREE(ro);
                        } else {
-                               /*
-                                * PMTU check versus smallest asoc MTU goes
-                                * here
-                                */
-                               if ((ro->ro_rt != NULL) &&
-                                   (net->ro._s_addr)) {
+                               if ((ro->ro_rt != NULL) && (net->ro._s_addr) &&
+                                   ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 
0)) {
                                        uint32_t mtu;
 
                                        mtu = 
SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
@@ -4635,8 +4631,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
                                        }
                                        net->src_addr_selected = 0;
                                }
-                               if ((ro->ro_rt != NULL) &&
-                                   (net->ro._s_addr)) {
+                               if ((ro->ro_rt != NULL) && (net->ro._s_addr) &&
+                                   ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 
0)) {
                                        uint32_t mtu;
 
                                        mtu = 
SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);

Modified: stable/11/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/11/sys/netinet/sctp_pcb.c    Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet/sctp_pcb.c    Sat Apr  7 20:08:17 2018        
(r332222)
@@ -2577,6 +2577,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
        /* number of streams to pre-open on a association */
        m->pre_open_stream_count = 
SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default);
 
+       m->default_mtu = 0;
        /* Add adaptation cookie */
        m->adaptation_layer_indicator = 0;
        m->adaptation_layer_indicator_provided = 0;
@@ -3942,7 +3943,28 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct soc
                    net,
                    0,
                    stcb->asoc.vrf_id);
-               if (net->ro._s_addr != NULL) {
+               if (stcb->asoc.default_mtu > 0) {
+                       net->mtu = stcb->asoc.default_mtu;
+                       switch (net->ro._l_addr.sa.sa_family) {
+#ifdef INET
+                       case AF_INET:
+                               net->mtu += SCTP_MIN_V4_OVERHEAD;
+                               break;
+#endif
+#ifdef INET6
+                       case AF_INET6:
+                               net->mtu += SCTP_MIN_OVERHEAD;
+                               break;
+#endif
+                       default:
+                               break;
+                       }
+#if defined(INET) || defined(INET6)
+                       if (net->port) {
+                               net->mtu += (uint32_t)sizeof(struct udphdr);
+                       }
+#endif
+               } else if (net->ro._s_addr != NULL) {
                        uint32_t imtu, rmtu, hcmtu;
 
                        net->src_addr_selected = 1;
@@ -3966,19 +3988,42 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct soc
                }
        }
        if (net->mtu == 0) {
-               switch (newaddr->sa_family) {
+               if (stcb->asoc.default_mtu > 0) {
+                       net->mtu = stcb->asoc.default_mtu;
+                       switch (net->ro._l_addr.sa.sa_family) {
 #ifdef INET
-               case AF_INET:
-                       net->mtu = SCTP_DEFAULT_MTU;
-                       break;
+                       case AF_INET:
+                               net->mtu += SCTP_MIN_V4_OVERHEAD;
+                               break;
 #endif
 #ifdef INET6
-               case AF_INET6:
-                       net->mtu = 1280;
-                       break;
+                       case AF_INET6:
+                               net->mtu += SCTP_MIN_OVERHEAD;
+                               break;
 #endif
-               default:
-                       break;
+                       default:
+                               break;
+                       }
+#if defined(INET) || defined(INET6)
+                       if (net->port) {
+                               net->mtu += (uint32_t)sizeof(struct udphdr);
+                       }
+#endif
+               } else {
+                       switch (newaddr->sa_family) {
+#ifdef INET
+                       case AF_INET:
+                               net->mtu = SCTP_DEFAULT_MTU;
+                               break;
+#endif
+#ifdef INET6
+                       case AF_INET6:
+                               net->mtu = 1280;
+                               break;
+#endif
+                       default:
+                               break;
+                       }
                }
        }
 #if defined(INET) || defined(INET6)

Modified: stable/11/sys/netinet/sctp_pcb.h
==============================================================================
--- stable/11/sys/netinet/sctp_pcb.h    Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet/sctp_pcb.h    Sat Apr  7 20:08:17 2018        
(r332222)
@@ -287,6 +287,7 @@ struct sctp_pcb {
        sctp_auth_chklist_t *local_auth_chunks;
        sctp_hmaclist_t *local_hmacs;
        uint16_t default_keyid;
+       uint32_t default_mtu;
 
        /* various thresholds */
        /* Max times I will init at a guy */

Modified: stable/11/sys/netinet/sctp_structs.h
==============================================================================
--- stable/11/sys/netinet/sctp_structs.h        Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet/sctp_structs.h        Sat Apr  7 20:08:17 2018        
(r332222)
@@ -1098,6 +1098,7 @@ struct sctp_association {
        uint32_t chunks_on_out_queue;   /* total chunks floating around,
                                         * locked by send socket buffer */
        uint32_t peers_adaptation;
+       uint32_t default_mtu;
        uint16_t peer_hmac_id;  /* peer HMAC id to send */
 
        /*

Modified: stable/11/sys/netinet/sctp_usrreq.c
==============================================================================
--- stable/11/sys/netinet/sctp_usrreq.c Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet/sctp_usrreq.c Sat Apr  7 20:08:17 2018        
(r332222)
@@ -202,6 +202,10 @@ sctp_notify(struct sctp_inpcb *inp,
 #endif
                /* no need to unlock here, since the TCB is gone */
        } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) {
+               if ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0) {
+                       SCTP_TCB_UNLOCK(stcb);
+                       return;
+               }
                /* Find the next (smaller) MTU */
                if (next_mtu == 0) {
                        /*
@@ -2447,7 +2451,7 @@ flags_out:
                                         * value
                                         */
                                        paddrp->spp_pathmaxrxt = 
stcb->asoc.def_net_failure;
-                                       paddrp->spp_pathmtu = 0;
+                                       paddrp->spp_pathmtu = 
stcb->asoc.default_mtu;
                                        if (stcb->asoc.default_dscp & 0x01) {
                                                paddrp->spp_dscp = 
stcb->asoc.default_dscp & 0xfc;
                                                paddrp->spp_flags |= SPP_DSCP;
@@ -2494,8 +2498,7 @@ flags_out:
                                                paddrp->spp_flags |= 
SPP_IPV6_FLOWLABEL;
                                        }
 #endif
-                                       /* can't return this */
-                                       paddrp->spp_pathmtu = 0;
+                                       paddrp->spp_pathmtu = 
inp->sctp_ep.default_mtu;
 
                                        if (sctp_is_feature_off(inp, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
                                                paddrp->spp_flags |= 
SPP_HB_ENABLE;
@@ -5479,6 +5482,7 @@ sctp_setopt(struct socket *so, int optname, void *optv
                                                                
sctp_pathmtu_adjustment(stcb, net->mtu);
                                                        }
                                                }
+                                               stcb->asoc.default_mtu = 
paddrp->spp_pathmtu;
                                                sctp_stcb_feature_on(inp, stcb, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD);
                                        }
                                        if (paddrp->spp_flags & 
SPP_PMTUD_ENABLE) {
@@ -5488,6 +5492,7 @@ sctp_setopt(struct socket *so, int optname, void *optv
                                                        }
                                                        net->dest_state &= 
~SCTP_ADDR_NO_PMTUD;
                                                }
+                                               stcb->asoc.default_mtu = 0;
                                                sctp_stcb_feature_off(inp, 
stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
                                        }
                                        if (paddrp->spp_flags & SPP_DSCP) {
@@ -5544,8 +5549,12 @@ sctp_setopt(struct socket *so, int optname, void *optv
                                                sctp_feature_on(inp, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
                                        }
                                        if (paddrp->spp_flags & 
SPP_PMTUD_ENABLE) {
+                                               inp->sctp_ep.default_mtu = 0;
                                                sctp_feature_off(inp, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD);
                                        } else if (paddrp->spp_flags & 
SPP_PMTUD_DISABLE) {
+                                               if (paddrp->spp_pathmtu >= 
SCTP_SMALLEST_PMTU) {
+                                                       
inp->sctp_ep.default_mtu = paddrp->spp_pathmtu;
+                                               }
                                                sctp_feature_on(inp, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD);
                                        }
                                        if (paddrp->spp_flags & SPP_DSCP) {

Modified: stable/11/sys/netinet/sctputil.c
==============================================================================
--- stable/11/sys/netinet/sctputil.c    Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet/sctputil.c    Sat Apr  7 20:08:17 2018        
(r332222)
@@ -1042,6 +1042,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb
        asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max;
        asoc->initial_rto = inp->sctp_ep.initial_rto;
 
+       asoc->default_mtu = inp->sctp_ep.default_mtu;
        asoc->max_init_times = inp->sctp_ep.max_init_times;
        asoc->max_send_times = inp->sctp_ep.max_send_times;
        asoc->def_net_failure = inp->sctp_ep.def_net_failure;

Modified: stable/11/sys/netinet6/sctp6_usrreq.c
==============================================================================
--- stable/11/sys/netinet6/sctp6_usrreq.c       Sat Apr  7 20:06:50 2018        
(r332221)
+++ stable/11/sys/netinet6/sctp6_usrreq.c       Sat Apr  7 20:08:17 2018        
(r332222)
@@ -229,6 +229,10 @@ sctp6_notify(struct sctp_inpcb *inp,
                }
                break;
        case ICMP6_PACKET_TOO_BIG:
+               if ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0) {
+                       SCTP_TCB_UNLOCK(stcb);
+                       break;
+               }
                if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
                        timer_stopped = 1;
                        sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, 
stcb, net,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to