diff options
author | Randall Stewart <rrs@FreeBSD.org> | 2007-07-14 09:36:28 +0000 |
---|---|---|
committer | Randall Stewart <rrs@FreeBSD.org> | 2007-07-14 09:36:28 +0000 |
commit | b54d3a6c48b9608d35248ff39cba565f8bbbfb00 (patch) | |
tree | 008308315d74a9df2eec618692844a82f1ace245 /sys/netinet/sctp_usrreq.c | |
parent | 46dd1e6ee739ed7df6e956613c42035d60d78dc5 (diff) | |
download | src-b54d3a6c48b9608d35248ff39cba565f8bbbfb00.tar.gz src-b54d3a6c48b9608d35248ff39cba565f8bbbfb00.zip |
- Modular congestion control, with RFC2581 being the default.
- CMT_PF states added (w/sysctl to turn the PF version on)
- sctp_input.c had a missing incr of cookie case when the
auth was bad. This meant a free was called without an
increment to refcnt, added increment like rest of code.
- There was a case, unlikely, when the scope of the destination
changed (this is a TSNH case). In that case, it would not free
the alloc'ed asoc (in sctp_input.c).
- When listed addresses found a colliding cookie/Init, then
the collided upon tcb was not unlocked in sctp_pcb.c
- Add error checking on arguments of sctp_sendx(3) to prevent it from
referencing a NULL pointer.
- Fix an error return of sctp_sendx(3), it was returing
ENOMEM not -1.
- Get assoc id was changed to use the sanctified socket api
method for getting a assoc id (PEER_ADDR_INFO instead of
PEER_ADDR_PARAMS).
- Fix it so a peeled off socket will get a proper error return
if it trys to send to a different address then it is connected to.
- Fix so that select_a_stream can avoid an endless loop that
could hang a caller.
- time_entered (state set time) was not being set in all cases
to the time we went established.
Approved by: re(ken smith)
Notes
Notes:
svn path=/head/; revision=171440
Diffstat (limited to 'sys/netinet/sctp_usrreq.c')
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 131 |
1 files changed, 129 insertions, 2 deletions
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index a62497ca547d..6461c9150d0d 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_timer.h> #include <netinet/sctp_auth.h> #include <netinet/sctp_bsd_addr.h> +#include <netinet/sctp_cc_functions.h> @@ -61,6 +62,7 @@ sctp_init(void) sctp_pcb_init(); + if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE) sctp_max_chunks_on_queue = (nmbclusters / 8); /* @@ -77,7 +79,6 @@ sctp_init(void) */ sctp_recvspace = sctp_sendspace; - } @@ -261,6 +262,26 @@ sctp_notify(struct sctp_inpcb *inp, net->dest_state &= ~SCTP_ADDR_REACHABLE; net->dest_state |= SCTP_ADDR_NOT_REACHABLE; + /* + * JRS 5/14/07 - If a destination is + * unreachable, the PF bit is turned off. + * This allows an unambiguous use of the PF + * bit for destinations that are reachable + * but potentially failed. If the + * destination is set to the unreachable + * state, also set the destination to the PF + * state. + */ + /* + * Add debug message here if destination is + * not in PF state. + */ + /* Stop any running T3 timers here? */ + if (sctp_cmt_pf) { + net->dest_state &= ~SCTP_ADDR_PF; + SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n", + net); + } net->error_count = net->failure_threshold + 1; sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_FAILED_THRESHOLD, @@ -487,6 +508,7 @@ sctp_attach(struct socket *so, int proto, struct thread *p) #ifdef IPSEC uint32_t flags; + #endif inp = (struct sctp_inpcb *)so->so_pcb; if (inp != 0) { @@ -1537,6 +1559,22 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize, *optsize = sizeof(*av); } break; + /* JRS - Get socket option for pluggable congestion control */ + case SCTP_PLUGGABLE_CC: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + if (stcb) { + av->assoc_value = stcb->asoc.congestion_control_module; + SCTP_TCB_UNLOCK(stcb); + } else { + av->assoc_value = inp->sctp_ep.sctp_default_cc_module; + } + *optsize = sizeof(*av); + } + break; case SCTP_GET_ADDR_LEN: { struct sctp_assoc_value *av; @@ -2512,6 +2550,91 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } } break; + /* JRS - Set socket option for pluggable congestion control */ + case SCTP_PLUGGABLE_CC: + { + struct sctp_assoc_value *av; + + SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); + SCTP_FIND_STCB(inp, stcb, av->assoc_id); + if (stcb) { + switch (av->assoc_value) { + /* + * JRS - Standard TCP congestion + * control + */ + case SCTP_CC_RFC2581: + { + stcb->asoc.congestion_control_module = SCTP_CC_RFC2581; + stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param; + stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_cwnd_update_after_sack; + stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_cwnd_update_after_fr; + stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout; + stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo; + stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped; + stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output; + stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer; + SCTP_TCB_UNLOCK(stcb); + break; + } + /* + * JRS - High Speed TCP congestion + * control (Floyd) + */ + case SCTP_CC_HSTCP: + { + stcb->asoc.congestion_control_module = SCTP_CC_HSTCP; + stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_set_initial_cc_param; + stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_hs_cwnd_update_after_sack; + stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_hs_cwnd_update_after_fr; + stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_cwnd_update_after_timeout; + stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_cwnd_update_after_ecn_echo; + stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped; + stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output; + stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_cwnd_update_after_fr_timer; + SCTP_TCB_UNLOCK(stcb); + break; + } + /* JRS - HTCP congestion control */ + case SCTP_CC_HTCP: + { + stcb->asoc.congestion_control_module = SCTP_CC_HTCP; + stcb->asoc.cc_functions.sctp_set_initial_cc_param = &sctp_htcp_set_initial_cc_param; + stcb->asoc.cc_functions.sctp_cwnd_update_after_sack = &sctp_htcp_cwnd_update_after_sack; + stcb->asoc.cc_functions.sctp_cwnd_update_after_fr = &sctp_htcp_cwnd_update_after_fr; + stcb->asoc.cc_functions.sctp_cwnd_update_after_timeout = &sctp_htcp_cwnd_update_after_timeout; + stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo = &sctp_htcp_cwnd_update_after_ecn_echo; + stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped = &sctp_cwnd_update_after_packet_dropped; + stcb->asoc.cc_functions.sctp_cwnd_update_after_output = &sctp_cwnd_update_after_output; + stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer = &sctp_htcp_cwnd_update_after_fr_timer; + SCTP_TCB_UNLOCK(stcb); + break; + } + /* + * JRS - All other values are + * invalid + */ + default: + { + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + break; + } + } + } else { + switch (av->assoc_value) { + case SCTP_CC_RFC2581: + case SCTP_CC_HSTCP: + case SCTP_CC_HTCP: + inp->sctp_ep.sctp_default_cc_module = av->assoc_value; + break; + default: + error = EINVAL; + break; + }; + } + } + break; case SCTP_CLR_STAT_LOG: error = EOPNOTSUPP; break; @@ -3123,7 +3246,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, /************************NET SPECIFIC SET ******************/ if (paddrp->spp_flags & SPP_HB_DEMAND) { /* on demand HB */ - (void)sctp_send_hb(stcb, 1, net); + if (sctp_send_hb(stcb, 1, net) < 0) { + /* asoc destroyed */ + error = EINVAL; + break; + } } if (paddrp->spp_flags & SPP_HB_DISABLE) { net->dest_state |= SCTP_ADDR_NOHB; |