diff options
author | rrs <rrs@FreeBSD.org> | 2007-07-17 20:58:26 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-07-17 20:58:26 +0000 |
commit | baae800484b92bf7eee24218fdc96dca410b1846 (patch) | |
tree | 6c79e4122192f2fc2cd2730d66ed9af4e467112a /sys/netinet/sctp_indata.c | |
parent | eeef9fbdacbbff0d2c008a8f385bddf21f2b0f04 (diff) | |
download | FreeBSD-src-baae800484b92bf7eee24218fdc96dca410b1846.zip FreeBSD-src-baae800484b92bf7eee24218fdc96dca410b1846.tar.gz |
- added pre-checks to the bindx call.
- use proper tick gathering macro instead of ticks directly.
- Placed reasonable boundaries on sets that a user can do
that are converted to ticks from ms.
- Fix CMT_PF to always check to be sure CMT is on.
- Fix ticks use of CMT_PF.
- put back code to allow asconfs to be queued while INITs are in flight
and before the assoc is established.
- During window probes, an ack'd packet might be left with the window
probe mark on it causing it to be retransmitted. Change so that
the flight decrease macro clears the window_probe mark.
- Additional logging flight size/reading and ASOC LOG. This
is only enabled if you manually insert things into opt_sctp.h
since its a set of debug code only.
- Found an interesting SMP race in the way data was appended which
could cause a reader to lose a part of a message, had to
reorder when we marked the message was complete to after
the data was appended.
- bug in ADD-IP for the subset bound socket case when the peer has only
one address
- fix ASCONF implicit success/error handling case
- proper support of jails in Freebsd 6>
- copy out the timeval for the 64 bit sparc world on cookie-echo
alignment error crashes without this).
Approved by: re(Ken Smith)
Diffstat (limited to 'sys/netinet/sctp_indata.c')
-rw-r--r-- | sys/netinet/sctp_indata.c | 208 |
1 files changed, 110 insertions, 98 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 0d8bbac..27bdfd2 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -1611,16 +1611,20 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, */ strmseq = ntohs(ch->dp.stream_sequence); #ifdef SCTP_ASOCLOG_OF_TSNS + SCTP_TCB_LOCK_ASSERT(stcb); + if (asoc->tsn_in_at >= SCTP_TSN_LOG_SIZE) { + asoc->tsn_in_at = 0; + asoc->tsn_in_wrapped = 1; + } asoc->in_tsnlog[asoc->tsn_in_at].tsn = tsn; asoc->in_tsnlog[asoc->tsn_in_at].strm = strmno; asoc->in_tsnlog[asoc->tsn_in_at].seq = strmseq; asoc->in_tsnlog[asoc->tsn_in_at].sz = chk_length; asoc->in_tsnlog[asoc->tsn_in_at].flgs = chunk_flags; + asoc->in_tsnlog[asoc->tsn_in_at].stcb = (void *)stcb; + asoc->in_tsnlog[asoc->tsn_in_at].in_pos = asoc->tsn_in_at; + asoc->in_tsnlog[asoc->tsn_in_at].in_out = 1; asoc->tsn_in_at++; - if (asoc->tsn_in_at >= SCTP_TSN_LOG_SIZE) { - asoc->tsn_in_at = 0; - asoc->tsn_in_wrapped = 1; - } #endif if ((chunk_flags & SCTP_DATA_FIRST_FRAG) && (TAILQ_EMPTY(&asoc->resetHead)) && @@ -2998,7 +3002,8 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_calculate_rto(stcb, asoc, tp1->whoTo, - &tp1->sent_rcv_time); + &tp1->sent_rcv_time, + sctp_align_safe_nocopy); tp1->do_rtt = 0; } } @@ -3456,7 +3461,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, tp1->no_fr_allowed = 1; alt = tp1->whoTo; /* sa_ignore NO_NULL_CHK */ - if (sctp_cmt_pf) { + if (sctp_cmt_on_off && sctp_cmt_pf) { /* * JRS 5/18/07 - If CMT PF is on, * use the PF version of @@ -3730,7 +3735,6 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, /* First setup this one and get it moved back */ tp1->sent = SCTP_DATAGRAM_UNSENT; - tp1->window_probe = 0; if (sctp_logging_level & SCTP_FLIGHT_LOGGING_ENABLE) { sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP, tp1->whoTo->flight_size, @@ -3752,7 +3756,6 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb, if (chk->sent == SCTP_DATAGRAM_RESEND) { /* Another chunk to move */ chk->sent = SCTP_DATAGRAM_UNSENT; - chk->window_probe = 0; /* It should not be in flight */ TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); TAILQ_INSERT_AFTER(&asoc->send_queue, tp1, chk, sctp_next); @@ -3781,6 +3784,13 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd); } SCTP_TCB_LOCK_ASSERT(stcb); +#ifdef SCTP_ASOCLOG_OF_TSNS + stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cumack; + stcb->asoc.cumack_log_at++; + if (stcb->asoc.cumack_log_at > SCTP_TSN_LOG_SIZE) { + stcb->asoc.cumack_log_at = 0; + } +#endif asoc = &stcb->asoc; old_rwnd = asoc->peers_rwnd; if (compare_with_wrap(asoc->last_acked_seq, cumack, MAX_TSN)) { @@ -3864,103 +3874,101 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, if (compare_with_wrap(cumack, tp1->rec.data.TSN_seq, MAX_TSN) || cumack == tp1->rec.data.TSN_seq) { - if (tp1->sent != SCTP_DATAGRAM_UNSENT) { + if (tp1->sent == SCTP_DATAGRAM_UNSENT) { + printf("Warning, an unsent is now acked?\n"); + } + /* + * ECN Nonce: Add the nonce to the sender's + * nonce sum + */ + asoc->nonce_sum_expect_base += tp1->rec.data.ect_nonce; + if (tp1->sent < SCTP_DATAGRAM_ACKED) { /* - * ECN Nonce: Add the nonce to the - * sender's nonce sum + * If it is less than ACKED, it is + * now no-longer in flight. Higher + * values may occur during marking */ - asoc->nonce_sum_expect_base += tp1->rec.data.ect_nonce; - if (tp1->sent < SCTP_DATAGRAM_ACKED) { - /* - * If it is less than ACKED, - * it is now no-longer in - * flight. Higher values may - * occur during marking - */ - if (tp1->sent < SCTP_DATAGRAM_RESEND) { - if (sctp_logging_level & SCTP_FLIGHT_LOGGING_ENABLE) { - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA, - tp1->whoTo->flight_size, - tp1->book_size, - (uintptr_t) tp1->whoTo, - tp1->rec.data.TSN_seq); - } - sctp_flight_size_decrease(tp1); - sctp_total_flight_decrease(stcb, tp1); - } - tp1->whoTo->net_ack += tp1->send_size; - if (tp1->snd_count < 2) { - /* - * True - * non-retransmited - * chunk - */ - tp1->whoTo->net_ack2 += - tp1->send_size; - - /* update RTO too? */ - if (tp1->do_rtt) { - tp1->whoTo->RTO = - sctp_calculate_rto(stcb, - asoc, tp1->whoTo, - &tp1->sent_rcv_time); - tp1->do_rtt = 0; - } + if (tp1->sent < SCTP_DATAGRAM_RESEND) { + if (sctp_logging_level & SCTP_FLIGHT_LOGGING_ENABLE) { + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); } + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); + } + tp1->whoTo->net_ack += tp1->send_size; + if (tp1->snd_count < 2) { /* - * CMT: CUCv2 algorithm. - * From the cumack'd TSNs, - * for each TSN being acked - * for the first time, set - * the following variables - * for the corresp - * destination. - * new_pseudo_cumack will - * trigger a cwnd update. - * find_(rtx_)pseudo_cumack - * will trigger search for - * the next expected - * (rtx-)pseudo-cumack. + * True non-retransmited + * chunk */ - tp1->whoTo->new_pseudo_cumack = 1; - tp1->whoTo->find_pseudo_cumack = 1; - tp1->whoTo->find_rtx_pseudo_cumack = 1; + tp1->whoTo->net_ack2 += + tp1->send_size; - if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) { - sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); + /* update RTO too? */ + if (tp1->do_rtt) { + tp1->whoTo->RTO = + sctp_calculate_rto(stcb, + asoc, tp1->whoTo, + &tp1->sent_rcv_time, + sctp_align_safe_nocopy); + tp1->do_rtt = 0; } } - if (tp1->sent == SCTP_DATAGRAM_RESEND) { - sctp_ucount_decr(asoc->sent_queue_retran_cnt); - } - if (tp1->rec.data.chunk_was_revoked) { - /* deflate the cwnd */ - tp1->whoTo->cwnd -= tp1->book_size; - tp1->rec.data.chunk_was_revoked = 0; + /* + * CMT: CUCv2 algorithm. From the + * cumack'd TSNs, for each TSN being + * acked for the first time, set the + * following variables for the + * corresp destination. + * new_pseudo_cumack will trigger a + * cwnd update. + * find_(rtx_)pseudo_cumack will + * trigger search for the next + * expected (rtx-)pseudo-cumack. + */ + tp1->whoTo->new_pseudo_cumack = 1; + tp1->whoTo->find_pseudo_cumack = 1; + tp1->whoTo->find_rtx_pseudo_cumack = 1; + + if (sctp_logging_level & SCTP_CWND_LOGGING_ENABLE) { + sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK); } - tp1->sent = SCTP_DATAGRAM_ACKED; } + if (tp1->sent == SCTP_DATAGRAM_RESEND) { + sctp_ucount_decr(asoc->sent_queue_retran_cnt); + } + if (tp1->rec.data.chunk_was_revoked) { + /* deflate the cwnd */ + tp1->whoTo->cwnd -= tp1->book_size; + tp1->rec.data.chunk_was_revoked = 0; + } + tp1->sent = SCTP_DATAGRAM_ACKED; + TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); + if (tp1->data) { + sctp_free_bufspace(stcb, asoc, tp1, 1); + sctp_m_freem(tp1->data); + } + if (sctp_logging_level & SCTP_SACK_LOGGING_ENABLE) { + sctp_log_sack(asoc->last_acked_seq, + cumack, + tp1->rec.data.TSN_seq, + 0, + 0, + SCTP_LOG_FREE_SENT); + } + tp1->data = NULL; + asoc->sent_queue_cnt--; + sctp_free_a_chunk(stcb, tp1); + tp1 = tp2; } else { break; } - TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - if (tp1->data) { - sctp_free_bufspace(stcb, asoc, tp1, 1); - sctp_m_freem(tp1->data); - } - if (sctp_logging_level & SCTP_SACK_LOGGING_ENABLE) { - sctp_log_sack(asoc->last_acked_seq, - cumack, - tp1->rec.data.TSN_seq, - 0, - 0, - SCTP_LOG_FREE_SENT); - } - tp1->data = NULL; - asoc->sent_queue_cnt--; - sctp_free_a_chunk(stcb, tp1); - tp1 = tp2; } + } if (stcb->sctp_socket) { SOCKBUF_LOCK(&stcb->sctp_socket->so_snd); @@ -4268,6 +4276,13 @@ sctp_handle_sack(struct mbuf *m, int offset, SCTP_STAT_INCR(sctps_slowpath_sack); nonce_sum_flag = ch->ch.chunk_flags & SCTP_SACK_NONCE_SUM; cum_ack = last_tsn = ntohl(sack->cum_tsn_ack); +#ifdef SCTP_ASOCLOG_OF_TSNS + stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cum_ack; + stcb->asoc.cumack_log_at++; + if (stcb->asoc.cumack_log_at > SCTP_TSN_LOG_SIZE) { + stcb->asoc.cumack_log_at = 0; + } +#endif num_seg = ntohs(sack->num_gap_ack_blks); a_rwnd = rwnd; @@ -4491,7 +4506,8 @@ sctp_handle_sack(struct mbuf *m, int offset, tp1->whoTo->RTO = sctp_calculate_rto(stcb, asoc, tp1->whoTo, - &tp1->sent_rcv_time); + &tp1->sent_rcv_time, + sctp_align_safe_nocopy); tp1->do_rtt = 0; } } @@ -4626,15 +4642,11 @@ skip_segments: } if (tp1->sent == SCTP_DATAGRAM_UNSENT) { /* no more sent on list */ - break; + printf("Warning, tp1->sent == %d and its now acked?\n", + tp1->sent); } tp2 = TAILQ_NEXT(tp1, sctp_next); TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - /* - * Friendlier printf in lieu of panic now that I think its - * fixed - */ - if (tp1->pr_sctp_on) { if (asoc->pr_sctp_cnt != 0) asoc->pr_sctp_cnt--; |