diff options
author | rrs <rrs@FreeBSD.org> | 2006-11-11 22:44:12 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2006-11-11 22:44:12 +0000 |
commit | fb5651e047ba819adc96c9f9e76b4559123edf34 (patch) | |
tree | 7a67d3389c46e84245fca92a06dcb77f66dbafcb /sys/netinet/sctp_input.c | |
parent | 26d0f2fab6f6582478cd2a21695844600a1bd490 (diff) | |
download | FreeBSD-src-fb5651e047ba819adc96c9f9e76b4559123edf34.zip FreeBSD-src-fb5651e047ba819adc96c9f9e76b4559123edf34.tar.gz |
In a true restart case, the send_lock was
not being aquired. This meant that when we cleanup
the outbound we may have one in transit to be
added with the old sequence number. This is bad
since then we loose a message :(
Also the report_outbound needed to have the right
lock when its called which it did not.. I added
the lock with of course a flag since we want to
have the lock before we call it in the restart
case.
This also fixed the FIX ME case where, in the cookie
collision case, we mark for retransmit any that
were bundled with the cookie that was dropped.
This also means changes to the output routine
so we can assure getting the COOKIE-ACK sent
BEFORE we retransmit the Data.
Approved by: gnn
Diffstat (limited to 'sys/netinet/sctp_input.c')
-rw-r--r-- | sys/netinet/sctp_input.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 86ed9f8..69d441c 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -701,7 +701,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp, if (!TAILQ_EMPTY(&asoc->send_queue) || !TAILQ_EMPTY(&asoc->sent_queue) || !TAILQ_EMPTY(&asoc->out_wheel)) { - sctp_report_all_outbound(stcb); + sctp_report_all_outbound(stcb, 0); } /* stop the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net); @@ -1092,6 +1092,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, int chk_length; int init_offset, initack_offset; int retval; + int spec_flag = 0; /* I know that the TCB is non-NULL from the caller */ asoc = &stcb->asoc; @@ -1271,18 +1272,31 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); } - /* - * FIX? Should we go out, in this case (if the seq numbers - * changed on the peer) and set any data to RETRANSMIT? - */ asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); - asoc->pre_open_streams = - ntohs(initack_cp->init.num_outbound_streams); + asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); + + /* Note last_cwr_tsn? where is this used? */ asoc->last_cwr_tsn = asoc->init_seq_number - 1; - asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; - asoc->str_reset_seq_in = asoc->init_seq_number; - asoc->advanced_peer_ack_point = asoc->last_acked_seq; + if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { + /* + * Ok the peer probably discarded our data (if we + * echoed a cookie+data). So anything on the + * sent_queue should be marked for retransmit, we + * may not get something to kick us so it COULD + * still take a timeout to move these.. but it can't + * hurt to mark them. + */ + struct sctp_tmit_chunk *chk; + + TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { + if (chk->sent < SCTP_DATAGRAM_RESEND) { + chk->sent = SCTP_DATAGRAM_RESEND; + stcb->asoc.sent_queue_retran_cnt++; + spec_flag++; + } + } + } /* process the INIT info (peer's info) */ retval = sctp_process_init(init_cp, stcb, net); if (retval < 0) { @@ -1316,6 +1330,16 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, } sctp_stop_all_cookie_timers(stcb); sctp_send_cookie_ack(stcb); + if (spec_flag) { + /* + * only if we have retrans set do we do this. What + * this call does is get only the COOKIE-ACK out and + * then when we return the normal call to + * sctp_chunk_output will get the retrans out behind + * this. + */ + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK); + } return (stcb); } if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && @@ -1336,7 +1360,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* send up all the data */ - sctp_report_all_outbound(stcb); + SCTP_TCB_SEND_LOCK(stcb); + sctp_report_all_outbound(stcb, 1); /* process the INIT-ACK info (my info) */ asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); @@ -1376,6 +1401,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, memset(asoc->mapping_array, 0, asoc->mapping_array_size); /* process the INIT info (peer's info) */ + SCTP_TCB_SEND_UNLOCK(stcb); retval = sctp_process_init(init_cp, stcb, net); if (retval < 0) { return (NULL); @@ -2356,7 +2382,7 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp, if (!TAILQ_EMPTY(&asoc->send_queue) || !TAILQ_EMPTY(&asoc->sent_queue) || !TAILQ_EMPTY(&asoc->out_wheel)) { - sctp_report_all_outbound(stcb); + sctp_report_all_outbound(stcb, 0); } } /* stop the timer */ |