From fb6f6fd9a183da8573afa302e42cdf7684785a7d Mon Sep 17 00:00:00 2001 From: rrs Date: Sat, 14 Apr 2007 09:44:09 +0000 Subject: [PATCH] - fix source address selection when picking an acceptable address - name change of prefered -> preferred - CMT fast recover code added. - Comment fixes in CMT. - We were not giving a reason of cant_start_asoc per socket api if we failed to get init/or/cookie to bring up an assoc. Change so we don't just give a generic "comm lost" but look at actual states of dying assoc. - change "crc32" arguments to "crc32c" to silence strict/noisy compiler warnings when crc32() is also declared - A few minor tweaks to get the portable stuff truely portable for sctp6_usrreq.c :-D - one-2-one style vrf match problem. - window recovery would leave chks marked for retran during window probes on the sent queue. This would then cause an out-of-order problem and assure that the flight size "problem" would occur. - Solves a flight size logging issue that caused rwnd overruns, flight size off as well as false retransmissions.g - Macroize the up and down of flight size. - Fix a ECNE bug in its counting. - The strict_sacks options was causing aborts when window probing was active, fix to make strict sacks a bit smarter about what the next unsent TSN is. - Fixes a one-2-one wakeup bug found by Martin Kulas. - If-defed out form, Andre's copy routines pending his commit of at least m_last().. need to adjust for 6.2 as well.. since m_last won't exist. Reviewed by: gnn --- sys/netinet/sctp_constants.h | 12 +- sys/netinet/sctp_crc32.c | 22 +- sys/netinet/sctp_indata.c | 417 +++++++++++++++++------------------ sys/netinet/sctp_input.c | 20 +- sys/netinet/sctp_output.c | 210 ++++++++++-------- sys/netinet/sctp_pcb.c | 24 +- sys/netinet/sctp_peeloff.c | 2 + sys/netinet/sctp_timer.c | 96 ++++---- sys/netinet/sctp_uio.h | 5 +- sys/netinet/sctp_usrreq.c | 20 +- sys/netinet/sctp_var.h | 51 +++++ sys/netinet/sctputil.c | 14 +- sys/netinet6/sctp6_usrreq.c | 48 ++-- 13 files changed, 510 insertions(+), 431 deletions(-) diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h index 9cd54321d574..cf301a237e73 100644 --- a/sys/netinet/sctp_constants.h +++ b/sys/netinet/sctp_constants.h @@ -186,9 +186,17 @@ __FBSDID("$FreeBSD$"); #define SCTP_RANDY_STUFF1 103 #define SCTP_STRMOUT_LOG_ASSIGN 104 #define SCTP_STRMOUT_LOG_SEND 105 -#define SCTP_FLIGHT_LOG_DOWN 106 +#define SCTP_FLIGHT_LOG_DOWN_CA 106 #define SCTP_FLIGHT_LOG_UP 107 -#define SCTP_LOG_MAX_TYPES 108 +#define SCTP_FLIGHT_LOG_DOWN_GAP 108 +#define SCTP_FLIGHT_LOG_DOWN_RSND 109 +#define SCTP_FLIGHT_LOG_UP_RSND 110 +#define SCTP_FLIGHT_LOG_DOWN_RSND_TO 111 +#define SCTP_FLIGHT_LOG_DOWN_WP 112 +#define SCTP_FLIGHT_LOG_UP_REVOKE 113 +#define SCTP_FLIGHT_LOG_DOWN_PDRP 114 +#define SCTP_FLIGHT_LOG_DOWN_PMTU 115 +#define SCTP_LOG_MAX_TYPES 116 /* * To turn on various logging, you must first define SCTP_STAT_LOGGING. Then * to get something to log you define one of the logging defines i.e. diff --git a/sys/netinet/sctp_crc32.c b/sys/netinet/sctp_crc32.c index 47f548352ddb..8f4d8fe07110 100644 --- a/sys/netinet/sctp_crc32.c +++ b/sys/netinet/sctp_crc32.c @@ -579,17 +579,17 @@ sctp_crc32c_sb8_64_bit(uint32_t crc, * none */ uint32_t -update_crc32(uint32_t crc32, +update_crc32(uint32_t crc32c, unsigned char *buffer, unsigned int length) { uint32_t offset; if (length == 0) { - return (crc32); + return (crc32c); } offset = ((uintptr_t) buffer) & 0x3; - return (sctp_crc32c_sb8_64_bit(crc32, buffer, length, offset)); + return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, offset)); } uint32_t sctp_crc_c[256] = { @@ -663,21 +663,21 @@ uint32_t sctp_crc_c[256] = { #define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF]) uint32_t -old_update_crc32(uint32_t crc32, +old_update_crc32(uint32_t crc32c, unsigned char *buffer, unsigned int length) { unsigned int i; for (i = 0; i < length; i++) { - SCTP_CRC32C(crc32, buffer[i]); + SCTP_CRC32C(crc32c, buffer[i]); } - return (crc32); + return (crc32c); } uint32_t -sctp_csum_finalize(uint32_t crc32) +sctp_csum_finalize(uint32_t crc32c) { uint32_t result; @@ -686,7 +686,7 @@ sctp_csum_finalize(uint32_t crc32) #endif /* Complement the result */ - result = ~crc32; + result = ~crc32c; #if BYTE_ORDER == BIG_ENDIAN /* * For BIG-ENDIAN.. aka Motorola byte order the result is in @@ -697,16 +697,16 @@ sctp_csum_finalize(uint32_t crc32) byte1 = (result >> 8) & 0x000000ff; byte2 = (result >> 16) & 0x000000ff; byte3 = (result >> 24) & 0x000000ff; - crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); + crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3); #else /* * For INTEL platforms the result comes out in network order. No * htonl is required or the swap above. So we optimize out both the * htonl and the manual swap above. */ - crc32 = result; + crc32c = result; #endif - return (crc32); + return (crc32c); } #endif diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 4d142f713cf0..2522148b2c24 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -2881,18 +2881,13 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, * value to the sender's * nonce sum */ - if (tp1->sent < SCTP_DATAGRAM_ACKED) { - /* - * If it is less - * than ACKED, it is - * now no-longer in - * flight. Higher - * values may - * already be set - * via previous Gap - * Ack Blocks... - * i.e. ACKED or - * MARKED. + if (tp1->sent < SCTP_DATAGRAM_RESEND) { + /*- + * If it is less than RESEND, it is + * now no-longer in flight. + * Higher values may already be set + * via previous Gap Ack Blocks... + * i.e. ACKED or RESEND. */ if (compare_with_wrap(tp1->rec.data.TSN_seq, *biggest_newly_acked_tsn, MAX_TSN)) { @@ -2927,7 +2922,7 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, if (*this_sack_lowest_newack == 0) { #ifdef SCTP_SACK_LOGGING sctp_log_sack(*this_sack_lowest_newack, - last_tsn, + v last_tsn, tp1->rec.data.TSN_seq, 0, 0, @@ -2985,28 +2980,16 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_LOG_TSN_ACKED); #endif #ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN, + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP, tp1->whoTo->flight_size, tp1->book_size, - (uintptr_t) stcb, + (uintptr_t) tp1->whoTo, tp1->rec.data.TSN_seq); #endif - if (tp1->whoTo->flight_size >= tp1->book_size) - tp1->whoTo->flight_size -= tp1->book_size; - else - tp1->whoTo->flight_size = 0; - - if (asoc->total_flight >= tp1->book_size) { - asoc->total_flight -= tp1->book_size; - if (asoc->total_flight_count > 0) - asoc->total_flight_count--; - } else { - asoc->total_flight = 0; - asoc->total_flight_count = 0; - } + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); tp1->whoTo->net_ack += tp1->send_size; - if (tp1->snd_count < 2) { /* * True @@ -3028,25 +3011,28 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, } } } - if (tp1->sent <= SCTP_DATAGRAM_RESEND && - tp1->sent != SCTP_DATAGRAM_UNSENT && - compare_with_wrap(tp1->rec.data.TSN_seq, - asoc->this_sack_highest_gap, - MAX_TSN)) { - asoc->this_sack_highest_gap = - tp1->rec.data.TSN_seq; - } - if (tp1->sent == SCTP_DATAGRAM_RESEND) { - sctp_ucount_decr(asoc->sent_queue_retran_cnt); + if (tp1->sent <= SCTP_DATAGRAM_RESEND) { + (*ecn_seg_sums) += tp1->rec.data.ect_nonce; + (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM; + if (compare_with_wrap(tp1->rec.data.TSN_seq, + asoc->this_sack_highest_gap, + MAX_TSN)) { + asoc->this_sack_highest_gap = + tp1->rec.data.TSN_seq; + } + if (tp1->sent == SCTP_DATAGRAM_RESEND) { + sctp_ucount_decr(asoc->sent_queue_retran_cnt); #ifdef SCTP_AUDITING_ENABLED - sctp_audit_log(0xB2, - (asoc->sent_queue_retran_cnt & 0x000000ff)); + sctp_audit_log(0xB2, + (asoc->sent_queue_retran_cnt & 0x000000ff)); #endif - + } } - (*ecn_seg_sums) += tp1->rec.data.ect_nonce; - (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM; - + /* + * All chunks NOT UNSENT + * fall through here and are + * marked + */ tp1->sent = SCTP_DATAGRAM_MARKED; if (tp1->rec.data.chunk_was_revoked) { /* deflate the cwnd */ @@ -3074,7 +3060,8 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, } static void -sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack, +sctp_check_for_revoked(struct sctp_tcb *stcb, + struct sctp_association *asoc, uint32_t cumack, u_long biggest_tsn_acked) { struct sctp_tmit_chunk *tp1; @@ -3098,15 +3085,20 @@ sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack, * We must add this stuff back in to assure * timers and such get started. */ - tp1->whoTo->flight_size += tp1->book_size; +#ifdef SCTP_FLIGHT_LOGGING + sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); +#endif + sctp_flight_size_increase(tp1); + sctp_total_flight_increase(stcb, tp1); /* * We inflate the cwnd to compensate for our * artificial inflation of the flight_size. */ tp1->whoTo->cwnd += tp1->book_size; - asoc->total_flight_count++; - asoc->total_flight += tp1->book_size; - tot_revoked++; #ifdef SCTP_SACK_LOGGING sctp_log_sack(asoc->last_acked_seq, @@ -3247,8 +3239,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * No new acks were receieved for data sent to this * dest. Therefore, according to the SFR algo for * CMT, no data sent to this dest can be marked for - * FR using this SACK. (iyengar@cis.udel.edu, - * 2005/05/12) + * FR using this SACK. */ tp1 = TAILQ_NEXT(tp1, sctp_next); continue; @@ -3298,11 +3289,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * cumack earlier. If not already to be * rtx'd, If not a mixed sack and if tp1 is * not between two sacked TSNs, then mark by - * one more. - */ - /* - * Jana FIX, does this mean you strike it - * twice (see code above?) + * one more. NOTE that we are marking by one + * additional time since the SACK DAC flag + * indicates that two packets have been + * received after this missing TSN. */ if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && compare_with_wrap(this_sack_lowest_newack, tp1->rec.data.TSN_seq, MAX_TSN)) { @@ -3367,7 +3357,13 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * If not a mixed sack and * if tp1 is not between two * sacked TSNs, then mark by - * one more. + * one more. NOTE that we + * are marking by one + * additional time since the + * SACK DAC flag indicates + * that two packets have + * been received after this + * missing TSN. */ if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && @@ -3418,7 +3414,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * cumack earlier. If not already to be * rtx'd, If not a mixed sack and if tp1 is * not between two sacked TSNs, then mark by - * one more. + * one more. NOTE that we are marking by one + * additional time since the SACK DAC flag + * indicates that two packets have been + * received after this missing TSN. */ if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) && compare_with_wrap(this_sack_lowest_newack, tp1->rec.data.TSN_seq, MAX_TSN)) { @@ -3521,17 +3520,14 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, } /* fix counts and things */ #ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN, + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND, tp1->whoTo->flight_size, tp1->book_size, - (uintptr_t) stcb, + (uintptr_t) tp1->whoTo, tp1->rec.data.TSN_seq); #endif tp1->whoTo->net_ack++; - if (tp1->whoTo->flight_size >= tp1->book_size) - tp1->whoTo->flight_size -= tp1->book_size; - else - tp1->whoTo->flight_size = 0; + sctp_flight_size_decrease(tp1); #ifdef SCTP_LOG_RWND sctp_log_rwnd(SCTP_INCREASE_PEER_RWND, @@ -3541,16 +3537,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->peers_rwnd += (tp1->send_size + sctp_peer_chunk_oh); /* remove from the total flight */ - if (asoc->total_flight >= tp1->book_size) { - asoc->total_flight -= tp1->book_size; - if (asoc->total_flight_count > 0) - asoc->total_flight_count--; - } else { - asoc->total_flight = 0; - asoc->total_flight_count = 0; - } - - + sctp_total_flight_decrease(stcb, tp1); if (alt != tp1->whoTo) { /* yes, there is an alternate. */ sctp_free_remote_addr(tp1->whoTo); @@ -3950,7 +3937,7 @@ sctp_cwnd_update(struct sctp_tcb *stcb, */ #endif - if (asoc->fast_retran_loss_recovery && will_exit == 0) { + if (asoc->fast_retran_loss_recovery && will_exit == 0 && sctp_cmt_on_off == 0) { /* * If we are in loss recovery we skip any cwnd * update @@ -4071,45 +4058,12 @@ skip_cwnd_update: } } -static int sctp_anal_print = 0; - static void -sctp_print_fs_audit(struct sctp_association *asoc) +sctp_fs_audit(struct sctp_association *asoc) { - int cnt, i; struct sctp_tmit_chunk *chk; int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0; - printf("sdqc:%d stqc:%d retran:%d reasm:%d cnt:%d tot_flight:%d tfc:%d\n", - (int)asoc->send_queue_cnt, - (int)asoc->sent_queue_cnt, - (int)asoc->sent_queue_retran_cnt, - (int)asoc->size_on_reasm_queue, - (int)asoc->cnt_on_reasm_queue, - (int)asoc->total_flight, - (int)asoc->total_flight_count); - printf("my_rwnd:%d peers_rwnd:%d asoc calc cumack:%x\n", - (int)asoc->my_rwnd, (int)asoc->peers_rwnd, asoc->last_acked_seq); - for (i = 0; i < asoc->streamoutcnt; i++) { - struct sctp_stream_queue_pending *sp; - - cnt = 0; - TAILQ_FOREACH(sp, &asoc->strmout[i].outqueue, next) - cnt++; - if (cnt) { - printf("Stream %d has %d msgs yet to be sent in strm queue\n", i, cnt); - } - } - cnt = 0; - TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) { - cnt++; - } - printf("The control_send_queue has %d pending\n", cnt); - cnt = 0; - TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { - cnt++; - } - printf("The send_queue (waiting to get in flight) has %d chunks pending\n", cnt); TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { if (chk->sent < SCTP_DATAGRAM_RESEND) { inflight++; @@ -4121,14 +4075,58 @@ sctp_print_fs_audit(struct sctp_association *asoc) above++; } else { acked++; - printf("chk->sent:%x chk->tsn:%x\n", - chk->sent, chk->rec.data.TSN_seq); } } - printf("The sent_queue stats inflight:%d resend:%d acked:%d above:%d inbetween:%d\n", - inflight, resend, acked, above, inbetween); + if ((inflight > 0) || (inbetween > 0)) { + panic("Flight size-express incorrect? \n"); + } } + +static void +sctp_window_probe_recovery(struct sctp_tcb *stcb, + struct sctp_association *asoc, + struct sctp_nets *net, + struct sctp_tmit_chunk *tp1) +{ + struct sctp_tmit_chunk *chk; + + /* First setup this one and get it moved back */ + tp1->sent = SCTP_DATAGRAM_UNSENT; + tp1->window_probe = 0; +#ifdef SCTP_FLIGHT_LOGGING + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); +#endif + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); + TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); + TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next); + asoc->sent_queue_cnt--; + asoc->send_queue_cnt++; + /* + * Now all guys marked for RESEND on the sent_queue must be moved + * back too. + */ + TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { + 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); + asoc->sent_queue_cnt--; + asoc->send_queue_cnt++; + sctp_ucount_decr(asoc->sent_queue_retran_cnt); + } + } +} + + void sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, uint32_t rwnd, int nonce_sum_flag, int *abort_now) @@ -4138,6 +4136,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, struct sctp_tmit_chunk *tp1, *tp2; uint32_t old_rwnd; int win_probe_recovery = 0; + int win_probe_recovered = 0; int j, done_once;; SCTP_TCB_LOCK_ASSERT(stcb); @@ -4162,19 +4161,22 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, if (sctp_strict_sacks) { uint32_t send_s; - if (TAILQ_EMPTY(&asoc->send_queue)) { - send_s = asoc->sending_seq; + if (!TAILQ_EMPTY(&asoc->sent_queue)) { + tp1 = TAILQ_LAST(&asoc->sent_queue, + sctpchunk_listhead); + send_s = tp1->rec.data.TSN_seq + 1; } else { - tp1 = TAILQ_FIRST(&asoc->send_queue); - send_s = tp1->rec.data.TSN_seq; + send_s = asoc->sending_seq; } if ((cumack == send_s) || compare_with_wrap(cumack, send_s, MAX_TSN)) { -#ifdef INVARIANTS /* for testing only */ - panic("Impossible sack 1"); -#else +#ifndef INVARIANTS struct mbuf *oper; +#endif +#ifdef INVARIANTS + panic("Impossible sack 1"); +#else *abort_now = 1; /* XXX */ oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), @@ -4221,27 +4223,17 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, * flight. Higher values may * occur during marking */ + if (tp1->sent < SCTP_DATAGRAM_RESEND) { #ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN, - tp1->whoTo->flight_size, - tp1->book_size, - (uintptr_t) stcb, - tp1->rec.data.TSN_seq); + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); #endif - if (tp1->whoTo->flight_size >= tp1->book_size) { - tp1->whoTo->flight_size -= tp1->book_size; - } else { - tp1->whoTo->flight_size = 0; - } - - if (asoc->total_flight >= tp1->book_size) { - asoc->total_flight -= tp1->book_size; - if (asoc->total_flight_count > 0) - asoc->total_flight_count--; - } else { - asoc->total_flight = 0; - asoc->total_flight_count = 0; + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); } tp1->whoTo->net_ack += tp1->send_size; if (tp1->snd_count < 2) { @@ -4414,6 +4406,7 @@ again: TAILQ_FOREACH(net, &asoc->nets, sctp_next) { if (win_probe_recovery && (net->window_probe)) { net->window_probe = 0; + win_probe_recovered = 1; /* * Find first chunk that was used with window probe * and clear the sent @@ -4421,15 +4414,7 @@ again: TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { if (tp1->window_probe) { /* move back to data send queue */ - tp1->sent = SCTP_DATAGRAM_UNSENT; - tp1->window_probe = 0; - net->flight_size -= tp1->book_size; - asoc->total_flight -= tp1->book_size; - TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next); - asoc->sent_queue_cnt--; - asoc->send_queue_cnt++; - asoc->total_flight_count--; + sctp_window_probe_recovery(stcb, asoc, net, tp1); break; } } @@ -4463,12 +4448,10 @@ again: if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0) && + (win_probe_recovered == 0) && (done_once == 0)) { /* huh, this should not happen */ - if (sctp_anal_print == 0) { - printf("Flight size-express incorrect? cumack:%x\n", cumack); - sctp_print_fs_audit(asoc); - } + sctp_fs_audit(asoc); TAILQ_FOREACH(net, &asoc->nets, sctp_next) { net->flight_size = 0; } @@ -4477,18 +4460,12 @@ again: asoc->sent_queue_retran_cnt = 0; TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { if (tp1->sent < SCTP_DATAGRAM_RESEND) { - tp1->whoTo->flight_size += tp1->book_size; - asoc->total_flight += tp1->book_size; - asoc->total_flight_count++; + sctp_flight_size_increase(tp1); + sctp_total_flight_increase(stcb, tp1); } else if (tp1->sent == SCTP_DATAGRAM_RESEND) { asoc->sent_queue_retran_cnt++; } } - if (sctp_anal_print == 0) { - printf("After audit, totalflight:%d, retran_cnt:%d\n", - asoc->total_flight, asoc->sent_queue_retran_cnt); - sctp_anal_print = 1; - } done_once = 1; goto again; } @@ -4597,12 +4574,13 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, uint16_t num_seg, num_dup; uint16_t wake_him = 0; unsigned int sack_length; - uint32_t send_s; + uint32_t send_s = 0; long j; int accum_moved = 0; int will_exit_fast_recovery = 0; uint32_t a_rwnd, old_rwnd; int win_probe_recovery = 0; + int win_probe_recovered = 0; struct sctp_nets *net = NULL; int nonce_sum_flag, ecn_seg_sums = 0; int done_once; @@ -4685,22 +4663,26 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, } } #endif - /* reality check */ - if (TAILQ_EMPTY(&asoc->send_queue)) { - send_s = asoc->sending_seq; - } else { - tp1 = TAILQ_FIRST(&asoc->send_queue); - send_s = tp1->rec.data.TSN_seq; - } - if (sctp_strict_sacks) { + /* reality check */ + if (!TAILQ_EMPTY(&asoc->sent_queue)) { + tp1 = TAILQ_LAST(&asoc->sent_queue, + sctpchunk_listhead); + send_s = tp1->rec.data.TSN_seq + 1; + } else { + send_s = asoc->sending_seq; + } if (cum_ack == send_s || compare_with_wrap(cum_ack, send_s, MAX_TSN)) { -#ifdef INVARIANTS /* for testing only */ +#ifndef INVARIANTS + struct mbuf *oper; + +#endif +#ifdef INVARIANTS hopeless_peer: panic("Impossible sack 1"); #else - struct mbuf *oper; + /* * no way, we have not even sent this TSN out yet. @@ -4826,25 +4808,16 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, tp1->whoTo->dest_state &= ~SCTP_ADDR_UNCONFIRMED; } + if (tp1->sent < SCTP_DATAGRAM_RESEND) { #ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN, - tp1->whoTo->flight_size, - tp1->book_size, - (uintptr_t) stcb, - tp1->rec.data.TSN_seq); + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); #endif - if (tp1->whoTo->flight_size >= tp1->book_size) { - tp1->whoTo->flight_size -= tp1->book_size; - } else { - tp1->whoTo->flight_size = 0; - } - if (asoc->total_flight >= tp1->book_size) { - asoc->total_flight -= tp1->book_size; - if (asoc->total_flight_count > 0) - asoc->total_flight_count--; - } else { - asoc->total_flight = 0; - asoc->total_flight_count = 0; + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); } tp1->whoTo->net_ack += tp1->send_size; @@ -5013,8 +4986,11 @@ skip_segments: } if ((TAILQ_FIRST(&asoc->sent_queue) == NULL) && (asoc->total_flight > 0)) { - printf("Warning flight size incorrect should be 0 is %d\n", - asoc->total_flight); + panic("Warning flight size is postive and should be 0"); +/* + printf("Warning flight size incorrect should be 0 is %d\n", + asoc->total_flight); +*/ asoc->total_flight = 0; } if (tp1->data) { @@ -5073,7 +5049,7 @@ done_with_it: */ if (num_seg) - sctp_check_for_revoked(asoc, cum_ack, biggest_tsn_acked); + sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked); else if (asoc->saw_sack_with_frags) { int cnt_revoked = 0; @@ -5084,8 +5060,16 @@ done_with_it: if ((tp1->sent > SCTP_DATAGRAM_RESEND) && (tp1->sent < SCTP_FORWARD_TSN_SKIP)) { tp1->sent = SCTP_DATAGRAM_SENT; +#ifdef SCTP_FLIGHT_LOGGING + sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE, + tp1->whoTo->flight_size, + tp1->book_size, + (uintptr_t) tp1->whoTo, + tp1->rec.data.TSN_seq); +#endif + sctp_flight_size_increase(tp1); + sctp_total_flight_increase(stcb, tp1); tp1->rec.data.chunk_was_revoked = 1; - tp1->whoTo->flight_size += tp1->book_size; /* * To ensure that this increase in * flightsize, which is artificial, @@ -5094,8 +5078,6 @@ done_with_it: * artificially. */ tp1->whoTo->cwnd += tp1->book_size; - asoc->total_flight_count++; - asoc->total_flight += tp1->book_size; cnt_revoked++; } } @@ -5282,12 +5264,10 @@ done_with_it: } /* * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) && - * (net->fast_retran_loss_recovery == 0))) if - * ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == - * 1)) { + * (net->fast_retran_loss_recovery == 0))) */ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - if (asoc->fast_retran_loss_recovery == 0) { + if ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == 1)) { /* out of a RFC2582 Fast recovery window? */ if (net->net_ack > 0) { /* @@ -5467,6 +5447,7 @@ again: TAILQ_FOREACH(net, &asoc->nets, sctp_next) { if (win_probe_recovery && (net->window_probe)) { net->window_probe = 0; + win_probe_recovered = 1; /*- * Find first chunk that was used with * window probe and clear the event. Put @@ -5475,15 +5456,7 @@ again: */ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { if (tp1->window_probe) { - tp1->sent = SCTP_DATAGRAM_UNSENT; - tp1->window_probe = 0; - net->flight_size -= tp1->book_size; - asoc->total_flight -= tp1->book_size; - TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next); - TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next); - asoc->sent_queue_cnt--; - asoc->send_queue_cnt++; - asoc->total_flight_count--; + sctp_window_probe_recovery(stcb, asoc, net, tp1); break; } } @@ -5492,18 +5465,28 @@ again: j++; sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net); + } else { + if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) { + sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, + stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_22); + } + if (sctp_early_fr) { + if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) { + SCTP_STAT_INCR(sctps_earlyfrstpidsck4); + sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net, + SCTP_FROM_SCTP_INDATA + SCTP_LOC_23); + } + } } } if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0) && + (win_probe_recovered == 0) && (done_once == 0)) { /* huh, this should not happen */ - if (sctp_anal_print == 0) { - printf("Flight size incorrect sack-cumack:%x prev_last_ack:%x? fixing??", - cum_ack, sav_cum_ack); - sctp_print_fs_audit(asoc); - } + sctp_fs_audit(asoc); TAILQ_FOREACH(net, &asoc->nets, sctp_next) { net->flight_size = 0; } @@ -5512,18 +5495,12 @@ again: asoc->sent_queue_retran_cnt = 0; TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { if (tp1->sent < SCTP_DATAGRAM_RESEND) { - tp1->whoTo->flight_size += tp1->book_size; - asoc->total_flight += tp1->book_size; - asoc->total_flight_count++; + sctp_flight_size_increase(tp1); + sctp_total_flight_increase(stcb, tp1); } else if (tp1->sent == SCTP_DATAGRAM_RESEND) { asoc->sent_queue_retran_cnt++; } } - if (sctp_anal_print == 0) { - printf("After audit, totalflight:%d retran count:%d\n", - asoc->total_flight, asoc->sent_queue_retran_cnt); - sctp_anal_print = 1; - } done_once = 1; goto again; } diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index afb85909265f..d451d8620869 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -2616,26 +2616,14 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, /* fix counts and things */ #ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN, + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, tp1->whoTo->flight_size, tp1->book_size, (uintptr_t) stcb, tp1->rec.data.TSN_seq); #endif - if (tp1->whoTo->flight_size >= tp1->book_size) - tp1->whoTo->flight_size -= tp1->book_size; - else - tp1->whoTo->flight_size = 0; - - if (stcb->asoc.total_flight >= tp1->book_size) { - stcb->asoc.total_flight -= tp1->book_size; - if (stcb->asoc.total_flight_count > 0) - stcb->asoc.total_flight_count--; - } else { - stcb->asoc.total_flight = 0; - stcb->asoc.total_flight_count = 0; - } - tp1->snd_count--; + sctp_flight_size_decrease(tp1); + sctp_total_flight_decrease(stcb, tp1); } { /* audit code */ unsigned int audit; @@ -4883,8 +4871,6 @@ sctp_skip_csum_4: } #endif /* IPSEC */ - - /* * common chunk processing */ diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index ccfd19799f79..e417d02221f4 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -2150,21 +2150,18 @@ skip_count: } static struct sctp_ifa * -sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa, +sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa, uint8_t dest_is_loop, uint8_t dest_is_priv, sa_family_t fam) { uint8_t dest_is_global = 0; - /* - * is_scope -> dest_is_priv is true if destination is a private - * address - */ + /* dest_is_priv is true if destination is a private address */ /* dest_is_loop is true if destination is a loopback addresses */ /* - * Here we determine if its a prefered address. A prefered address + * Here we determine if its a preferred address. A preferred address * means it is the same scope or higher scope then the destination. * L = loopback, P = private, G = global * ----------------------------------------- src | dest | result @@ -2189,7 +2186,7 @@ sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa, } #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { - printf("Is destination prefered:"); + printf("Is destination preferred:"); sctp_print_address(&ifa->address.sa); } #endif @@ -2280,7 +2277,7 @@ sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa, printf("YES\n"); } #endif - /* its a prefered address */ + /* its a preferred address */ return (ifa); } @@ -2334,15 +2331,14 @@ sctp_is_ifa_addr_acceptable(struct sctp_ifa *ifa, } } /* - * Now that we know what is what, implement or table this could in + * Now that we know what is what, implement our table. This could in * theory be done slicker (it used to be), but this is * straightforward and easier to validate :-) */ - - if ((ifa->src_is_loop == 0) && (dest_is_priv)) { + if ((ifa->src_is_loop == 1) && (dest_is_priv)) { return (NULL); } - if ((ifa->src_is_loop == 0) && (dest_is_global)) { + if ((ifa->src_is_loop == 1) && (dest_is_global)) { return (NULL); } /* its an acceptable address */ @@ -2427,15 +2423,15 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp, sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index); /* * first question, is the ifn we will emit on in our list, if so, we - * want such an address. Note that we first looked for a prefered + * want such an address. Note that we first looked for a preferred * address. */ if (sctp_ifn) { - /* is a prefered one on the interface we route out? */ + /* is a preferred one on the interface we route out? */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; - sifa = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_preferred(sctp_ifa, dest_is_loop, dest_is_priv, fam); if (sifa == NULL) continue; if (sctp_is_addr_in_ep(inp, sifa)) { @@ -2446,9 +2442,9 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp, } /* * ok, now we now need to find one on the list of the addresses. We - * can't get one on the emitting interface so lets find first a - * prefered one. If not that a acceptable one otherwise... we return - * NULL. + * can't get one on the emitting interface so let's find first a + * preferred one. If not that an acceptable one otherwise... we + * return NULL. */ starting_point = inp->next_addr_touse; once_again: @@ -2461,7 +2457,7 @@ once_again: /* address has been removed */ continue; } - sifa = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_preferred(laddr->ifa, dest_is_loop, dest_is_priv, fam); if (sifa == NULL) continue; atomic_add_int(&sifa->refcount, 1); @@ -2535,17 +2531,17 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp, sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index); /* - * first question, is the ifn we will emit on in our list, if so, we - * want that one.. First we look for a prefered. Second we go for an - * acceptable. + * first question, is the ifn we will emit on in our list? If so, + * we want that one. First we look for a preferred. Second, we go + * for an acceptable. */ if (sctp_ifn) { - /* first try for a prefered address on the ep */ + /* first try for a preferred address on the ep */ LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; if (sctp_is_addr_in_ep(inp, sctp_ifa)) { - sifa = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_preferred(sctp_ifa, dest_is_loop, dest_is_priv, fam); if (sifa == NULL) continue; if ((non_asoc_addr_ok == 0) && @@ -2578,7 +2574,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp, } /* * if we can't find one like that then we must look at all addresses - * bound to pick one at first prefereable then secondly acceptable. + * bound to pick one at first preferable then secondly acceptable. */ starting_point = stcb->asoc.last_used_address; sctp_from_the_top: @@ -2593,7 +2589,7 @@ sctp_from_the_top: /* address has been removed */ continue; } - sifa = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_preferred(laddr->ifa, dest_is_loop, dest_is_priv, fam); if (sifa == NULL) continue; if ((non_asoc_addr_ok == 0) && @@ -2645,7 +2641,7 @@ sctp_from_the_top2: } static struct sctp_ifa * -sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn, +sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn, struct sctp_tcb *stcb, int non_asoc_addr_ok, uint8_t dest_is_loop, @@ -2659,7 +2655,7 @@ sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn, LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) { if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) continue; - sifa = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_preferred(ifa, dest_is_loop, dest_is_priv, fam); if (sifa == NULL) continue; if (stcb) { @@ -2681,7 +2677,7 @@ sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn, static int -sctp_count_num_prefered_boundall(struct sctp_ifn *ifn, +sctp_count_num_preferred_boundall(struct sctp_ifn *ifn, struct sctp_tcb *stcb, int non_asoc_addr_ok, uint8_t dest_is_loop, @@ -2695,7 +2691,7 @@ sctp_count_num_prefered_boundall(struct sctp_ifn *ifn, if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) { continue; } - sifa = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_preferred(ifa, dest_is_loop, dest_is_priv, fam); if (sifa == NULL) { continue; } @@ -2724,7 +2720,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp, int non_asoc_addr_ok, sa_family_t fam) { - int cur_addr_num = 0, num_prefered = 0; + int cur_addr_num = 0, num_preferred = 0; void *ifn; struct sctp_ifn *sctp_ifn, *looked_at = NULL, *emit_ifn; struct sctp_ifa *sctp_ifa, *sifa; @@ -2732,10 +2728,10 @@ sctp_choose_boundall(struct sctp_inpcb *inp, struct sctp_vrf *vrf; /* - * For boundall we can use any address in the association. If + * For boundall we can use any address in the association. If * non_asoc_addr_ok is set we can use any address (at least in - * theory). So we look for prefered addresses first. If we find one, - * we use it. Otherwise we next try to get an address on the + * theory). So we look for preferred addresses first. If we find + * one, we use it. Otherwise we next try to get an address on the * interface, which we should be able to do (unless non_asoc_addr_ok * is false and we are routed out that way). In these cases where we * can't use the address of the interface we go through all the @@ -2760,17 +2756,17 @@ sctp_choose_boundall(struct sctp_inpcb *inp, if (net) { cur_addr_num = net->indx_of_eligible_next_to_use; } - num_prefered = sctp_count_num_prefered_boundall(sctp_ifn, + num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { - printf("Found %d prefered source addresses\n", num_prefered); + printf("Found %d preferred source addresses\n", num_preferred); } #endif - if (num_prefered == 0) { + if (num_preferred == 0) { /* * no eligible addresses, we must use some other interface * address if we can find one. @@ -2782,7 +2778,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp, * may vary from call to call due to addresses being deprecated * etc.. */ - if (cur_addr_num >= num_prefered) { + if (cur_addr_num >= num_preferred) { cur_addr_num = 0; } /* @@ -2794,7 +2790,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp, printf("cur_addr_num:%d\n", cur_addr_num); } #endif - sctp_ifa = sctp_select_nth_prefered_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, + sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, cur_addr_num, fam); /* if sctp_ifa is NULL something changed??, fall to plan b. */ @@ -2807,8 +2803,8 @@ sctp_choose_boundall(struct sctp_inpcb *inp, return (sctp_ifa); } /* - * plan_b: Look at all interfaces and find a prefered address. If no - * prefered fall through to plan_c. + * plan_b: Look at all interfaces and find a preferred address. If + * no preferred fall through to plan_c. */ bound_all_plan_b: #ifdef SCTP_DEBUG @@ -2824,14 +2820,14 @@ bound_all_plan_b: if ((sctp_ifn == looked_at) && looked_at) /* already looked at this guy */ continue; - num_prefered = sctp_count_num_prefered_boundall(sctp_ifn, stcb, non_asoc_addr_ok, + num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, fam); #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { - printf("Found ifn:%p %d prefered source addresses\n", ifn, num_prefered); + printf("Found ifn:%p %d preferred source addresses\n", ifn, num_preferred); } #endif - if (num_prefered == 0) { + if (num_preferred == 0) { /* * None on this interface. */ @@ -2839,8 +2835,8 @@ bound_all_plan_b: } #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { - printf("num prefered:%d on interface:%p cur_addr_num:%d\n", - num_prefered, + printf("num preferred:%d on interface:%p cur_addr_num:%d\n", + num_preferred, sctp_ifn, cur_addr_num); } @@ -2851,10 +2847,10 @@ bound_all_plan_b: * use, this may vary from call to call due to addresses * being deprecated etc.. */ - if (cur_addr_num >= num_prefered) { + if (cur_addr_num >= num_preferred) { cur_addr_num = 0; } - sifa = sctp_select_nth_prefered_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, + sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop, dest_is_priv, cur_addr_num, fam); if (sifa == NULL) continue; @@ -2881,18 +2877,21 @@ bound_all_plan_b: */ #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) { - printf("Plan C no prefered for Dest, acceptable for?\n"); + printf("Plan C no preferred for Dest, acceptable for?\n"); } #endif LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) { - if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) + if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && + (non_asoc_addr_ok == 0)) continue; - sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, + dest_is_priv, fam); if (sifa == NULL) continue; if (stcb) { - if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) { + if ((non_asoc_addr_ok == 0) && + sctp_is_addr_restricted(stcb, sifa)) { /* * It is restricted for some reason.. * probably not yet added. @@ -2905,7 +2904,7 @@ bound_all_plan_b: } /* - * plan_d: We are in trouble. No prefered address on the emit + * plan_d: We are in trouble. No preferred address on the emit * interface. And not even a perfered address on all interfaces. Go * out and see if we can find an acceptable address somewhere * amongst all interfaces. @@ -2925,13 +2924,17 @@ bound_all_plan_b: continue; LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { - if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) + if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && + (non_asoc_addr_ok == 0)) continue; - sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam); + sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, + dest_is_loop, + dest_is_priv, fam); if (sifa == NULL) continue; if (stcb) { - if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) { + if ((non_asoc_addr_ok == 0) && + sctp_is_addr_restricted(stcb, sifa)) { /* * It is restricted for some * reason.. probably not yet added. @@ -3019,12 +3022,10 @@ sctp_source_address_selection(struct sctp_inpcb *inp, * use the same concept but instead only consider the bound * addresses. If the bound set is NOT assigned to the interface then * we must use rotation amongst the bound addresses.. - * */ if (ro->ro_rt == NULL) { /* * Need a route to cache. - * */ rtalloc_ign(ro, 0UL); did_rtalloc = 1; @@ -3380,13 +3381,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, { /* * Given a mbuf chain (via SCTP_BUF_NEXT()) that holds a packet - * header WITH a SCTPHDR but no IP header, endpoint inp and sa - * structure. - fill in the HMAC digest of any AUTH chunk in the - * packet - calculate SCTP checksum and fill in - prepend a IP - * address header - if boundall use INADDR_ANY - if boundspecific do - * source address selection - set fragmentation option for ipV4 - On - * return from IP output, check/adjust mtu size - of output - * interface and smallest_mtu size as well. + * header WITH an SCTPHDR but no IP header, endpoint inp and sa + * structure: - fill in the HMAC digest of any AUTH chunk in the + * packet. - calculate and fill in the SCTP checksum. - prepend an + * IP address header. - if boundall use INADDR_ANY. - if + * boundspecific do source address selection. - set fragmentation + * option for ipV4. - On return from IP output, check/adjust mtu + * size of output interface and smallest_mtu size as well. */ /* Will need ifdefs around this */ struct mbuf *o_pak; @@ -3882,7 +3883,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, void sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) { - struct mbuf *m, *m_at, *m_last; + struct mbuf *m, *m_at, *mp_last; struct sctp_nets *net; struct sctp_init_msg *initm; struct sctp_supported_addr_param *sup_addr; @@ -3896,7 +3897,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) int p_len; /* INIT's always go to the primary (and usually ONLY address) */ - m_last = NULL; + mp_last = NULL; net = stcb->asoc.primary_destination; if (net == NULL) { net = TAILQ_FIRST(&stcb->asoc.nets); @@ -4119,7 +4120,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) p_len = 0; for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { if (SCTP_BUF_NEXT(m_at) == NULL) - m_last = m_at; + mp_last = m_at; p_len += SCTP_BUF_LEN(m_at); } initm->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr))); @@ -4130,15 +4131,15 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb) /* I don't expect this to execute but we will be safe here */ padval = p_len % 4; - if ((padval) && (m_last)) { + if ((padval) && (mp_last)) { /* - * The compiler worries that m_last may not be set even - * though I think it is impossible :-> however we add m_last - * here just in case. + * The compiler worries that mp_last may not be set even + * though I think it is impossible :-> however we add + * mp_last here just in case. */ int ret; - ret = sctp_add_pad_tombuf(m_last, (4 - padval)); + ret = sctp_add_pad_tombuf(mp_last, (4 - padval)); if (ret) { /* Houston we have a problem, no space */ sctp_m_freem(m); @@ -4514,7 +4515,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_init_chunk *init_chk) { struct sctp_association *asoc; - struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *m_last; + struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last; struct sctp_init_msg *initackm_out; struct sctp_ecn_supported_param *ecn; struct sctp_prsctp_supported_param *prsctp; @@ -4543,7 +4544,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, vrf_id = inp->def_vrf_id; asoc = NULL; } - m_last = NULL; + mp_last = NULL; if ((asoc != NULL) && (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) && (sctp_are_there_new_addresses(asoc, init_pkt, iphlen, offset))) { @@ -5088,7 +5089,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, p_len += SCTP_BUF_LEN(m_tmp); if (SCTP_BUF_NEXT(m_tmp) == NULL) { /* m_tmp should now point to last one */ - m_last = m_tmp; + mp_last = m_tmp; break; } } @@ -5098,11 +5099,11 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * here since the timer will drive a retranmission. */ padval = p_len % 4; - if ((padval) && (m_last)) { - /* see my previous comments on m_last */ + if ((padval) && (mp_last)) { + /* see my previous comments on mp_last */ int ret; - ret = sctp_add_pad_tombuf(m_last, (4 - padval)); + ret = sctp_add_pad_tombuf(mp_last, (4 - padval)); if (ret) { /* Houston we have a problem, no space */ sctp_m_freem(m); @@ -6034,12 +6035,11 @@ all_done: sctp_misc_ints(SCTP_FLIGHT_LOG_UP, data_list[i]->whoTo->flight_size, data_list[i]->book_size, - (uintptr_t) stcb, + (uintptr_t) data_list[i]->whoTo, data_list[i]->rec.data.TSN_seq); #endif - net->flight_size += data_list[i]->book_size; - asoc->total_flight += data_list[i]->book_size; - asoc->total_flight_count++; + sctp_flight_size_increase(data_list[i]); + sctp_total_flight_increase(stcb, data_list[i]); #ifdef SCTP_LOG_RWND sctp_log_rwnd(SCTP_DECREASE_PEER_RWND, asoc->peers_rwnd, data_list[i]->send_size, sctp_peer_chunk_oh); @@ -8250,7 +8250,6 @@ one_chunk_around: } else { - sctp_ucount_incr(asoc->total_flight_count); #ifdef SCTP_LOG_RWND sctp_log_rwnd(SCTP_DECREASE_PEER_RWND, asoc->peers_rwnd, data_list[i]->send_size, sctp_peer_chunk_oh); @@ -8260,14 +8259,14 @@ one_chunk_around: sctp_peer_chunk_oh)); } #ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_UP, + sctp_misc_ints(SCTP_FLIGHT_LOG_UP_RSND, data_list[i]->whoTo->flight_size, data_list[i]->book_size, - (uintptr_t) stcb, + (uintptr_t) data_list[i]->whoTo, data_list[i]->rec.data.TSN_seq); #endif - net->flight_size += data_list[i]->book_size; - asoc->total_flight += data_list[i]->book_size; + sctp_flight_size_increase(data_list[i]); + sctp_total_flight_increase(stcb, data_list[i]); if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) { /* SWS sender side engages */ asoc->peers_rwnd = 0; @@ -8970,7 +8969,6 @@ sctp_send_sack(struct sctp_tcb *stcb) gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk)); - siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8; if (asoc->cumulative_tsn < asoc->mapping_array_base_tsn) { offset = 1; @@ -10309,8 +10307,6 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, } } - - static struct mbuf * sctp_copy_resume(struct sctp_stream_queue_pending *sp, struct uio *uio, @@ -10321,6 +10317,22 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp, uint32_t * sndout, struct mbuf **new_tail) { + +/*#if defined(__FreeBSD__) && __FreeBSD_version >= 602000*/ +#if defined(_NOT_YET_) + + struct mbuf *m; + +/* take out max_hdr */ + m = m_uiotombuf(uio, M_WAITOK, max_send_len, 0, + (M_PKTHDR | (user_marks_eor ? M_EOR : 0))); + if (m == NULL) + *error = ENOMEM; + else + *sndout = m_length(m, NULL); + *new_tail = m_last(m); + return (m); +#else int left, cancpy, willcpy; struct mbuf *m, *prev, *head; @@ -10368,6 +10380,7 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp, } } return (head); +#endif } static int @@ -10375,7 +10388,19 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, struct uio *uio, int resv_upfront) { - int left, cancpy, willcpy, error; + int left; + +/*#if defined(__FreeBSD__) && __FreeBSD_version >= 602000*/ +#if defined(_NOT_YET_) + left = sp->length; + sp->data = m_uiotombuf(uio, M_WAITOK, 0, resv_upfront, M_PKTHDR); + if (sp->data == NULL) + return (ENOMEM); + sp->length = m_length(sp->data, NULL); + sp->tail_mbuf = m_last(sp->data); + return (0); +#else + int cancpy, willcpy, error; struct mbuf *m, *head; int cpsz = 0; @@ -10423,6 +10448,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp, sp->data = head; sp->length = cpsz; return (0); +#endif } diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 19dde5de7e5e..da7d86478954 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -476,7 +476,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, SCTP_INP_RUNLOCK(inp); continue; } - if (inp->def_vrf_id == vrf_id) { + if (inp->def_vrf_id != vrf_id) { SCTP_INP_RUNLOCK(inp); continue; } @@ -1143,7 +1143,7 @@ struct sctp_tcb * sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from, struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool, uint32_t vrf_id) { - struct sctp_inpcb *inp; + struct sctp_inpcb *inp = NULL; struct sctp_tcb *retval; SCTP_INP_INFO_RLOCK(); @@ -1954,7 +1954,7 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id) } else { /* t_inp is bound only V4 */ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && - SCTP_IPV6_V6ONLY(t_inp)) { + SCTP_IPV6_V6ONLY(inp)) { /* no conflict */ continue; } @@ -3549,17 +3549,33 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre } /* now clean up any other timers */ SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer); + asoc->hb_timer.self = NULL; SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); + asoc->dack_timer.self = NULL; SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); + /*- + * For stream reset we don't blast this unless + * it is a str-reset timer, it might be the + * free-asoc timer which we DON'T want to + * disturb. + */ + if (asoc->strreset_timer.type == SCTP_TIMER_TYPE_STRRESET) + asoc->strreset_timer.self = NULL; SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); + asoc->asconf_timer.self = NULL; SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); + asoc->autoclose_timer.self = NULL; SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); + asoc->shut_guard_timer.self = NULL; SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); - + asoc->delayed_event_timer.self = NULL; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { SCTP_OS_TIMER_STOP(&net->fr_timer.timer); + net->fr_timer.self = NULL; SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); + net->rxt_timer.self = NULL; SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); + net->pmtu_timer.self = NULL; } /* Now the read queue needs to be cleaned up (only once) */ cnt = 0; diff --git a/sys/netinet/sctp_peeloff.c b/sys/netinet/sctp_peeloff.c index 5950bbbec0a3..81f39242047a 100644 --- a/sys/netinet/sctp_peeloff.c +++ b/sys/netinet/sctp_peeloff.c @@ -105,6 +105,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id) return (0); } + struct socket * sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error) { @@ -177,6 +178,7 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error) SCTP_CLEAR_SO_NBIO(newso); newso->so_state |= SS_ISCONNECTED; /* We remove it right away */ + #ifdef SCTP_LOCK_LOGGING sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK); #endif diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 05865a7c985f..57ad30d964d3 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -460,9 +460,9 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, struct sctp_nets *lnets; struct timeval now, min_wait, tv; int cur_rtt; - int orig_rwnd, audit_tf, num_mk, fir; + int audit_tf, num_mk, fir; unsigned int cnt_mk; - uint32_t orig_flight; + uint32_t orig_flight, orig_tf; uint32_t tsnlast, tsnfirst; /* @@ -524,8 +524,9 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, * Our rwnd will be incorrect here since we are not adding back the * cnt * mbuf but we will fix that down below. */ - orig_rwnd = stcb->asoc.peers_rwnd; orig_flight = net->flight_size; + orig_tf = stcb->asoc.total_flight; + net->fast_retran_ip = 0; /* Now on to each chunk */ num_mk = cnt_mk = 0; @@ -617,7 +618,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, } continue; } - if (chk->sent != SCTP_DATAGRAM_RESEND) { + if (chk->sent < SCTP_DATAGRAM_RESEND) { sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); num_mk++; if (fir == 0) { @@ -630,33 +631,27 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, 0, SCTP_FR_T3_MARKED); #endif - } - if (stcb->asoc.total_flight_count > 0) - stcb->asoc.total_flight_count--; - if (chk->rec.data.chunk_was_revoked) { - /* deflate the cwnd */ - chk->whoTo->cwnd -= chk->book_size; - chk->rec.data.chunk_was_revoked = 0; + if (chk->rec.data.chunk_was_revoked) { + /* deflate the cwnd */ + chk->whoTo->cwnd -= chk->book_size; + chk->rec.data.chunk_was_revoked = 0; + } + net->marked_retrans++; + stcb->asoc.marked_retrans++; +#ifdef SCTP_FLIGHT_LOGGING + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO, + chk->whoTo->flight_size, + chk->book_size, + (uintptr_t) chk->whoTo, + chk->rec.data.TSN_seq); +#endif + sctp_flight_size_decrease(chk); + sctp_total_flight_decrease(stcb, chk); + stcb->asoc.peers_rwnd += chk->send_size; + stcb->asoc.peers_rwnd += sctp_peer_chunk_oh; } chk->sent = SCTP_DATAGRAM_RESEND; SCTP_STAT_INCR(sctps_markedretrans); - net->marked_retrans++; - stcb->asoc.marked_retrans++; -#ifdef SCTP_FLIGHT_LOGGING - sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN, - chk->whoTo->flight_size, - chk->book_size, - (uintptr_t) stcb, - chk->rec.data.TSN_seq); -#endif - - if (net->flight_size >= chk->book_size) - net->flight_size -= chk->book_size; - else - net->flight_size = 0; - - stcb->asoc.peers_rwnd += chk->send_size; - stcb->asoc.peers_rwnd += sctp_peer_chunk_oh; /* reset the TSN for striking and other FR stuff */ chk->rec.data.doing_fast_retransmit = 0; @@ -686,18 +681,13 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, cnt_mk++; } } + if ((orig_flight - net->flight_size) != (orig_tf - stcb->asoc.total_flight)) { + /* we did not subtract the same things? */ + audit_tf = 1; + } #if defined(SCTP_FR_LOGGING) || defined(SCTP_EARLYFR_LOGGING) sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT); #endif - - if (stcb->asoc.total_flight >= (orig_flight - net->flight_size)) { - stcb->asoc.total_flight -= (orig_flight - net->flight_size); - } else { - stcb->asoc.total_flight = 0; - stcb->asoc.total_flight_count = 0; - audit_tf = 1; - } - #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_TIMER1) { if (num_mk) { @@ -766,12 +756,12 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb, sctp_misc_ints(SCTP_FLIGHT_LOG_UP, chk->whoTo->flight_size, chk->book_size, - (uintptr_t) stcb, + (uintptr_t) chk->whoTo, chk->rec.data.TSN_seq); #endif - stcb->asoc.total_flight += chk->book_size; - chk->whoTo->flight_size += chk->book_size; - stcb->asoc.total_flight_count++; + + sctp_flight_size_increase(chk); + sctp_total_flight_increase(stcb, chk); } } } @@ -865,7 +855,29 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp, } else { win_probe = 0; } - alt = sctp_find_alternate_net(stcb, net, 0); + + if (sctp_cmt_on_off) { + /* + * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being + * used, then pick dest with largest ssthresh for any + * retransmission. + */ + alt = net; + alt = sctp_find_alternate_net(stcb, alt, 1); + /* + * CUCv2: If a different dest is picked for the + * retransmission, then new (rtx-)pseudo_cumack needs to be + * tracked for orig dest. Let CUCv2 track new (rtx-) + * pseudo-cumack always. + */ + net->find_pseudo_cumack = 1; + net->find_rtx_pseudo_cumack = 1; + + } else { /* CMT is OFF */ + + alt = sctp_find_alternate_net(stcb, net, 0); + } + sctp_mark_all_for_resend(stcb, net, alt, win_probe, &num_mk); /* FR Loss recovery just ended with the T3. */ stcb->asoc.fast_retran_loss_recovery = 0; diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h index 67051ca8e633..4130493c6e1b 100644 --- a/sys/netinet/sctp_uio.h +++ b/sys/netinet/sctp_uio.h @@ -872,6 +872,7 @@ struct sctpstat { u_long sctps_sends_with_abort; u_long sctps_protocol_drain_calls; u_long sctps_protocol_drains_done; + u_long sctps_read_peeks; }; #define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1) @@ -971,8 +972,8 @@ sctp_lower_sosend(struct socket *so, struct mbuf *control, int flags, int use_rcvinfo, - struct sctp_sndrcvinfo *srcv, - struct thread *p + struct sctp_sndrcvinfo *srcv + ,struct thread *p ); int diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 2b8be650cd09..f0f2c753830e 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -128,19 +128,17 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp, } chk->sent = SCTP_DATAGRAM_RESEND; chk->rec.data.doing_fast_retransmit = 0; - +#ifdef SCTP_FLIGHT_LOGGING + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU, + chk->whoTo->flight_size, + chk->book_size, + (uintptr_t) chk->whoTo, + chk->rec.data.TSN_seq); +#endif /* Clear any time so NO RTT is being done */ chk->do_rtt = 0; - if (stcb->asoc.total_flight >= chk->book_size) - stcb->asoc.total_flight -= chk->book_size; - else - stcb->asoc.total_flight = 0; - if (stcb->asoc.total_flight_count > 0) - stcb->asoc.total_flight_count--; - if (net->flight_size >= chk->book_size) - net->flight_size -= chk->book_size; - else - net->flight_size = 0; + sctp_flight_size_decrease(chk); + sctp_total_flight_decrease(stcb, chk); } } } diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h index 0fd0ae758e9d..ee322fa7ceff 100644 --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -231,6 +231,57 @@ extern struct pr_usrreqs sctp_usrreqs; } \ } while (0) +#ifdef RANDY_WILL_USE_LATER /* this will be the non-invarant version */ +#define sctp_flight_size_decrease(tp1) do { \ + if (tp1->whoTo->flight_size >= tp1->book_size) \ + tp1->whoTo->flight_size -= tp1->book_size; \ + else \ + tp1->whoTo->flight_size = 0; \ +} while (0) + + +#define sctp_total_flight_decrease(stcb, tp1) do { \ + if (stcb->asoc.total_flight >= tp1->book_size) { \ + stcb->asoc.total_flight -= tp1->book_size; \ + if (stcb->asoc.total_flight_count > 0) \ + stcb->asoc.total_flight_count--; \ + } else { \ + stcb->asoc.total_flight = 0; \ + stcb->asoc.total_flight_count = 0; \ + } \ +} while (0) + +#else + +#define sctp_flight_size_decrease(tp1) do { \ + if (tp1->whoTo->flight_size >= tp1->book_size) \ + tp1->whoTo->flight_size -= tp1->book_size; \ + else \ + panic("flight size corruption"); \ +} while (0) + + +#define sctp_total_flight_decrease(stcb, tp1) do { \ + if (stcb->asoc.total_flight >= tp1->book_size) { \ + stcb->asoc.total_flight -= tp1->book_size; \ + if (stcb->asoc.total_flight_count > 0) \ + stcb->asoc.total_flight_count--; \ + } else { \ + panic("total flight size corruption"); \ + } \ +} while (0) + +#endif + +#define sctp_flight_size_increase(tp1) do { \ + (tp1)->whoTo->flight_size += (tp1)->book_size; \ +} while (0) + + +#define sctp_total_flight_increase(stcb, tp1) do { \ + (stcb)->asoc.total_flight_count++; \ + (stcb)->asoc.total_flight += (tp1)->book_size; \ +} while (0) struct sctp_nets; struct sctp_inpcb; diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index 977ecef1b6c5..54aef9fbe710 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1404,7 +1404,9 @@ sctp_timeout_handler(void *t) } tmr->stopped_from = 0xa004; if (stcb) { + atomic_add_int(&stcb->asoc.refcnt, 1); if (stcb->asoc.state == 0) { + atomic_add_int(&stcb->asoc.refcnt, -1); if (inp) { SCTP_INP_DECR_REF(inp); } @@ -1426,7 +1428,6 @@ sctp_timeout_handler(void *t) tmr->stopped_from = 0xa006; if (stcb) { - atomic_add_int(&stcb->asoc.refcnt, 1); SCTP_TCB_LOCK(stcb); atomic_add_int(&stcb->asoc.refcnt, -1); } @@ -2706,7 +2707,7 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb, */ if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && - (event == SCTP_COMM_LOST)) { + ((event == SCTP_COMM_LOST) || (event == SCTP_SHUTDOWN_COMP))) { if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) stcb->sctp_socket->so_error = ECONNREFUSED; else @@ -3270,7 +3271,12 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, case SCTP_NOTIFY_STRDATA_ERR: break; case SCTP_NOTIFY_ASSOC_ABORTED: - sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL); + if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || + ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) { + sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, NULL); + } else { + sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL); + } break; case SCTP_NOTIFY_PEER_OPENED_STREAM: break; @@ -4488,6 +4494,8 @@ sctp_sorecvmsg(struct socket *so, if (msg_flags) { in_flags = *msg_flags; + if (in_flags & MSG_PEEK) + SCTP_STAT_INCR(sctps_read_peeks); } else { in_flags = 0; } diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index d08c1f75ad1b..eddc0aedb9af 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -31,33 +31,35 @@ #include __FBSDID("$FreeBSD$"); + #include #include #include #include #include +#if defined(INET6) +#include +#endif #include #include -#include -#include #include #include #include #include -#include #include #include -#include - +#include +#include extern struct protosw inetsw[]; + int -sctp6_input(mp, offp, proto) - struct mbuf **mp; +sctp6_input(i_pak, offp, proto) + struct mbuf **i_pak; int *offp; int proto; { @@ -76,7 +78,8 @@ sctp6_input(mp, offp, proto) int off = *offp; vrf_id = SCTP_DEFAULT_VRFID; - m = SCTP_HEADER_TO_CHAIN(*mp); + m = SCTP_HEADER_TO_CHAIN(*i_pak); + ip6 = mtod(m, struct ip6_hdr *); /* Ensure that (sctphdr + sctp_chunkhdr) in a row. */ @@ -100,7 +103,9 @@ sctp6_input(mp, offp, proto) SCTP_STAT_INCR_COUNTER64(sctps_inpackets); #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_INPUT1) { - printf("V6 input gets a packet iphlen:%d pktlen:%d\n", iphlen, SCTP_HEADER_LEN((*mp))); + printf("V6 input gets a packet iphlen:%d pktlen:%d\n", iphlen, + SCTP_HEADER_LEN((*i_pak)) + ); } #endif if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { @@ -200,7 +205,6 @@ sctp_skip_csum: } #endif /* IPSEC */ - /* * CONTROL chunk processing */ @@ -682,7 +686,8 @@ sctp_must_try_again: /* This could be made common with sctp_detach() since they are identical */ -static int +static +int sctp6_disconnect(struct socket *so) { struct sctp_inpcb *inp; @@ -715,23 +720,10 @@ sctp6_disconnect(struct socket *so) if (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) { /* Left with Data unread */ - struct mbuf *err; + struct mbuf *op_err; - err = NULL; - MGET(err, M_DONTWAIT, MT_DATA); - if (err) { - /* - * Fill in the user - * initiated abort - */ - struct sctp_paramhdr *ph; - - ph = mtod(err, struct sctp_paramhdr *); - SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr); - ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); - ph->param_length = htons(SCTP_BUF_LEN(err)); - } - sctp_send_abort_tcb(stcb, err); + op_err = sctp_generate_invmanparam(SCTP_CAUSE_USER_INITIATED_ABT); + sctp_send_abort_tcb(stcb, op_err); SCTP_STAT_INCR_COUNTER32(sctps_aborted); } SCTP_INP_RUNLOCK(inp); @@ -803,6 +795,7 @@ sctp6_disconnect(struct socket *so) } } + int sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct thread *p); @@ -1221,6 +1214,7 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam) in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6); memcpy(addr, &sin6, sizeof(struct sockaddr_in6)); + } } return (error);