diff options
author | tuexen <tuexen@FreeBSD.org> | 2011-09-17 08:50:29 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2011-09-17 08:50:29 +0000 |
commit | 680b9f90a2df45c87f6be8100faa097073b497b7 (patch) | |
tree | 1c66f8080b5b5458c7b294565b24b6e003093597 | |
parent | a5586859b8e8bec4079433cd96cd1cef0b10b335 (diff) | |
download | FreeBSD-src-680b9f90a2df45c87f6be8100faa097073b497b7.zip FreeBSD-src-680b9f90a2df45c87f6be8100faa097073b497b7.tar.gz |
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.
-rw-r--r-- | sys/netinet/sctp.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_constants.h | 1 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 7 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 48 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 3 |
5 files changed, 40 insertions, 20 deletions
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h index 11aa02a..394a7cd 100644 --- a/sys/netinet/sctp.h +++ b/sys/netinet/sctp.h @@ -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 diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index 4087c8d..5b74056 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -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 diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index b0f2880..9eb9a7d 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -4030,11 +4030,16 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, #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); diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 82a8cba..d49ea38 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -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 optname, void *optval, size_t optsize, 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 optname, void *optval, size_t optsize, } } 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 optname, void *optval, size_t optsize, 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 optname, void *optval, size_t optsize, } } } + 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 optname, void *optval, size_t optsize, 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 optname, void *optval, size_t optsize, } } } + 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 optname, void *optval, size_t optsize, } 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; diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 62fa0d1..5b8c3e5 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -2052,6 +2052,9 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 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; |