Author: tuexen
Date: Sat Sep 17 08:50:29 2011
New Revision: 225635
URL: http://svn.freebsd.org/changeset/base/225635

Log:
  Fix the enabling/disabling of Heartbeats and path MTU
  discovery when using the SCTP_PEER_ADDR_PARAMS socket option.
  Approved by: re
  MFC after: 1 month.

Modified:
  head/sys/netinet/sctp.h
  head/sys/netinet/sctp_constants.h
  head/sys/netinet/sctp_pcb.c
  head/sys/netinet/sctp_usrreq.c
  head/sys/netinet/sctputil.c

Modified: head/sys/netinet/sctp.h
==============================================================================
--- head/sys/netinet/sctp.h     Sat Sep 17 05:35:59 2011        (r225634)
+++ head/sys/netinet/sctp.h     Sat Sep 17 08:50:29 2011        (r225635)
@@ -496,6 +496,7 @@ struct sctp_error_unrecognized_chunk {
 /*
  * PCB Features (in sctp_features bitmask)
  */
+#define SCTP_PCB_FLAGS_DO_NOT_PMTUD     0x00000001
 #define SCTP_PCB_FLAGS_EXT_RCVINFO      0x00000002     /* deprecated */
 #define SCTP_PCB_FLAGS_DONOT_HEARTBEAT  0x00000004
 #define SCTP_PCB_FLAGS_FRAG_INTERLEAVE  0x00000008

Modified: head/sys/netinet/sctp_constants.h
==============================================================================
--- head/sys/netinet/sctp_constants.h   Sat Sep 17 05:35:59 2011        
(r225634)
+++ head/sys/netinet/sctp_constants.h   Sat Sep 17 08:50:29 2011        
(r225635)
@@ -508,6 +508,7 @@ __FBSDID("$FreeBSD$");
 
 /* SCTP reachability state for each address */
 #define SCTP_ADDR_REACHABLE            0x001
+#define SCTP_ADDR_NO_PMTUD              0x002
 #define SCTP_ADDR_NOHB                 0x004
 #define SCTP_ADDR_BEING_DELETED                0x008
 #define SCTP_ADDR_NOT_IN_ASSOC         0x010

Modified: head/sys/netinet/sctp_pcb.c
==============================================================================
--- head/sys/netinet/sctp_pcb.c Sat Sep 17 05:35:59 2011        (r225634)
+++ head/sys/netinet/sctp_pcb.c Sat Sep 17 08:50:29 2011        (r225635)
@@ -4030,11 +4030,16 @@ sctp_add_remote_addr(struct sctp_tcb *st
 #ifdef INET6
        net->flowlabel = stcb->asoc.default_flowlabel;
 #endif
-       if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
+       if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
                net->dest_state |= SCTP_ADDR_NOHB;
        } else {
                net->dest_state &= ~SCTP_ADDR_NOHB;
        }
+       if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
+               net->dest_state |= SCTP_ADDR_NO_PMTUD;
+       } else {
+               net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
+       }
        net->heart_beat_delay = stcb->asoc.heart_beat_delay;
        /* Init the timer structure */
        SCTP_OS_TIMER_INIT(&net->rxt_timer.timer);

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c      Sat Sep 17 05:35:59 2011        
(r225634)
+++ head/sys/netinet/sctp_usrreq.c      Sat Sep 17 08:50:29 2011        
(r225635)
@@ -2423,12 +2423,13 @@ flags_out:
                                        paddrp->spp_pathmaxrxt = 
net->failure_threshold;
                                        paddrp->spp_pathmtu = net->mtu - ovh;
                                        /* get flags for HB */
-                                       if (net->dest_state & SCTP_ADDR_NOHB)
+                                       if (net->dest_state & SCTP_ADDR_NOHB) {
                                                paddrp->spp_flags |= 
SPP_HB_DISABLE;
-                                       else
+                                       } else {
                                                paddrp->spp_flags |= 
SPP_HB_ENABLE;
+                                       }
                                        /* get flags for PMTU */
-                                       if 
(SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
+                                       if (net->dest_state & 
SCTP_ADDR_NO_PMTUD) {
                                                paddrp->spp_flags |= 
SPP_PMTUD_ENABLE;
                                        } else {
                                                paddrp->spp_flags |= 
SPP_PMTUD_DISABLE;
@@ -2449,8 +2450,6 @@ flags_out:
                                         * No destination so return default
                                         * value
                                         */
-                                       int cnt = 0;
-
                                        paddrp->spp_pathmaxrxt = 
stcb->asoc.def_net_failure;
                                        paddrp->spp_pathmtu = 
sctp_get_frag_point(stcb, &stcb->asoc);
                                        if (stcb->asoc.default_dscp & 0x01) {
@@ -2464,20 +2463,17 @@ flags_out:
                                        }
 #endif
                                        /* default settings should be these */
-                                       if (sctp_is_feature_on(stcb->sctp_ep, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
+                                       if (sctp_stcb_is_feature_on(inp, stcb, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
                                                paddrp->spp_flags |= 
SPP_HB_DISABLE;
                                        } else {
                                                paddrp->spp_flags |= 
SPP_HB_ENABLE;
                                        }
-                                       paddrp->spp_hbinterval = 
stcb->asoc.heart_beat_delay;
-                                       TAILQ_FOREACH(net, &stcb->asoc.nets, 
sctp_next) {
-                                               if 
(SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
-                                                       cnt++;
-                                               }
-                                       }
-                                       if (cnt) {
+                                       if (sctp_stcb_is_feature_on(inp, stcb, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
+                                               paddrp->spp_flags |= 
SPP_PMTUD_DISABLE;
+                                       } else {
                                                paddrp->spp_flags |= 
SPP_PMTUD_ENABLE;
                                        }
+                                       paddrp->spp_hbinterval = 
stcb->asoc.heart_beat_delay;
                                }
                                paddrp->spp_assoc_id = sctp_get_associd(stcb);
                                SCTP_TCB_UNLOCK(stcb);
@@ -2505,14 +2501,16 @@ flags_out:
                                        /* can't return this */
                                        paddrp->spp_pathmtu = 0;
 
-                                       /* default behavior, no stcb */
-                                       paddrp->spp_flags = SPP_PMTUD_ENABLE;
-
                                        if (sctp_is_feature_off(inp, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
                                                paddrp->spp_flags |= 
SPP_HB_ENABLE;
                                        } else {
                                                paddrp->spp_flags |= 
SPP_HB_DISABLE;
                                        }
+                                       if (sctp_is_feature_off(inp, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
+                                               paddrp->spp_flags |= 
SPP_PMTUD_ENABLE;
+                                       } else {
+                                               paddrp->spp_flags |= 
SPP_PMTUD_DISABLE;
+                                       }
                                        SCTP_INP_RUNLOCK(inp);
                                } else {
                                        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 
SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -4651,6 +4649,7 @@ sctp_setopt(struct socket *so, int optna
                                                        
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
                                                            
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
                                                }
+                                               net->dest_state |= 
SCTP_ADDR_NO_PMTUD;
                                                if (paddrp->spp_pathmtu > 
SCTP_DEFAULT_MINSEGMENT) {
                                                        net->mtu = 
paddrp->spp_pathmtu + ovh;
                                                        if (net->mtu < 
stcb->asoc.smallest_mtu) {
@@ -4659,9 +4658,10 @@ sctp_setopt(struct socket *so, int optna
                                                }
                                        }
                                        if (paddrp->spp_flags & 
SPP_PMTUD_ENABLE) {
-                                               if 
(SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
+                                               if 
(!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
                                                        
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
                                                }
+                                               net->dest_state &= 
~SCTP_ADDR_NO_PMTUD;
                                        }
                                        if (paddrp->spp_pathmaxrxt) {
                                                if (net->dest_state & 
SCTP_ADDR_PF) {
@@ -4754,9 +4754,9 @@ sctp_setopt(struct socket *so, int optna
                                                            
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
                                                        
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
                                                }
+                                               sctp_stcb_feature_off(inp, 
stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
                                        }
                                        if (paddrp->spp_flags & SPP_HB_DISABLE) 
{
-                                               /* Turn back on the timer */
                                                TAILQ_FOREACH(net, 
&stcb->asoc.nets, sctp_next) {
                                                        if (!(net->dest_state & 
SCTP_ADDR_NOHB)) {
                                                                net->dest_state 
|= SCTP_ADDR_NOHB;
@@ -4765,6 +4765,7 @@ sctp_setopt(struct socket *so, int optna
                                                                }
                                                        }
                                                }
+                                               sctp_stcb_feature_on(inp, stcb, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
                                        }
                                        if ((paddrp->spp_flags & 
SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
                                                TAILQ_FOREACH(net, 
&stcb->asoc.nets, sctp_next) {
@@ -4772,6 +4773,7 @@ sctp_setopt(struct socket *so, int optna
                                                                
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
                                                                    
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
                                                        }
+                                                       net->dest_state |= 
SCTP_ADDR_NO_PMTUD;
                                                        if (paddrp->spp_pathmtu 
> SCTP_DEFAULT_MINSEGMENT) {
                                                                net->mtu = 
paddrp->spp_pathmtu + ovh;
                                                                if (net->mtu < 
stcb->asoc.smallest_mtu) {
@@ -4779,13 +4781,16 @@ sctp_setopt(struct socket *so, int optna
                                                                }
                                                        }
                                                }
+                                               sctp_stcb_feature_on(inp, stcb, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD);
                                        }
                                        if (paddrp->spp_flags & 
SPP_PMTUD_ENABLE) {
                                                TAILQ_FOREACH(net, 
&stcb->asoc.nets, sctp_next) {
-                                                       if 
(SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
+                                                       if 
(!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
                                                                
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
                                                        }
+                                                       net->dest_state &= 
~SCTP_ADDR_NO_PMTUD;
                                                }
+                                               sctp_stcb_feature_off(inp, 
stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
                                        }
                                        if (paddrp->spp_flags & SPP_DSCP) {
                                                TAILQ_FOREACH(net, 
&stcb->asoc.nets, sctp_next) {
@@ -4840,6 +4845,11 @@ sctp_setopt(struct socket *so, int optna
                                        } else if (paddrp->spp_flags & 
SPP_HB_DISABLE) {
                                                sctp_feature_on(inp, 
SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
                                        }
+                                       if (paddrp->spp_flags & 
SPP_PMTUD_ENABLE) {
+                                               sctp_feature_off(inp, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD);
+                                       } else if (paddrp->spp_flags & 
SPP_PMTUD_DISABLE) {
+                                               sctp_feature_on(inp, 
SCTP_PCB_FLAGS_DO_NOT_PMTUD);
+                                       }
                                        if (paddrp->spp_flags & SPP_DSCP) {
                                                inp->sctp_ep.default_dscp = 
paddrp->spp_dscp << 2;
                                                inp->sctp_ep.default_dscp |= 
0x01;

Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c Sat Sep 17 05:35:59 2011        (r225634)
+++ head/sys/netinet/sctputil.c Sat Sep 17 08:50:29 2011        (r225635)
@@ -2052,6 +2052,9 @@ sctp_timer_start(int t_type, struct sctp
                if (net == NULL) {
                        return;
                }
+               if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
+                       return;
+               }
                to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
                tmr = &net->pmtu_timer;
                break;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to