diff options
Diffstat (limited to 'sys/netinet/sctp_indata.c')
-rw-r--r-- | sys/netinet/sctp_indata.c | 210 |
1 files changed, 104 insertions, 106 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 86945f7..517f1d1 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2001-2006, Cisco Systems, Inc. All rights reserved. + * Copyright (c) 2001-2007, Cisco Systems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_os.h> #include <netinet/sctp_var.h> +#include <netinet/sctp_sysctl.h> #include <netinet/sctp_pcb.h> #include <netinet/sctp_header.h> #include <netinet/sctputil.h> @@ -45,11 +46,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_timer.h> -#ifdef SCTP_DEBUG -extern uint32_t sctp_debug_on; - -#endif - /* * NOTES: On the outbound side of things I need to check the sack timer to * see if I should generate a sack into the chunk queue (if I have data to @@ -60,8 +56,6 @@ extern uint32_t sctp_debug_on; * the list. */ -extern int sctp_strict_sacks; - __inline void sctp_set_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc) { @@ -1438,7 +1432,6 @@ sctp_does_tsn_belong_to_reasm(struct sctp_association *asoc, } -extern unsigned int sctp_max_chunks_on_queue; static int sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, struct mbuf **m, int offset, struct sctp_data_chunk *ch, int chk_length, @@ -1505,15 +1498,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, asoc->dup_tsns[asoc->numduptsns] = tsn; asoc->numduptsns++; } - if (!SCTP_OS_TIMER_PENDING(&asoc->dack_timer.timer)) { - /* - * By starting the timer we assure that we WILL sack - * at the end of the packet when sctp_sack_check - * gets called. - */ - sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, - stcb, NULL); - } + asoc->send_sack = 1; return (0); } /* @@ -2382,19 +2367,18 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort */ stcb->asoc.cmt_dac_pkts_rcvd++; - if ((stcb->asoc.first_ack_sent == 0) || /* First time we send a - * sack */ + if ((stcb->asoc.send_sack == 1) || /* We need to send a + * SACK */ ((was_a_gap) && (is_a_gap == 0)) || /* was a gap, but no * longer is one */ (stcb->asoc.numduptsns) || /* we have dup's */ (is_a_gap) || /* is still a gap */ - (stcb->asoc.delayed_ack == 0) || - (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) /* timer was up . second - * packet */ + (stcb->asoc.delayed_ack == 0) || /* Delayed sack disabled */ + (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */ ) { if ((sctp_cmt_on_off) && (sctp_cmt_use_dac) && - (stcb->asoc.first_ack_sent == 1) && + (stcb->asoc.send_sack == 0) && (stcb->asoc.numduptsns == 0) && (stcb->asoc.delayed_ack) && (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) { @@ -2420,13 +2404,14 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort * first packet OR there are gaps or * duplicates. */ - stcb->asoc.first_ack_sent = 1; SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); sctp_send_sack(stcb); } } else { - sctp_timer_start(SCTP_TIMER_TYPE_RECV, - stcb->sctp_ep, stcb, NULL); + if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { + sctp_timer_start(SCTP_TIMER_TYPE_RECV, + stcb->sctp_ep, stcb, NULL); + } } } } @@ -2488,8 +2473,6 @@ doit_again: } } -extern int sctp_strict_data_order; - int sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, struct sctphdr *sh, struct sctp_inpcb *inp, struct sctp_tcb *stcb, @@ -2573,6 +2556,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, */ *high_tsn = asoc->cumulative_tsn; break_flag = 0; + asoc->data_pkts_seen++; while (stop_proc == 0) { /* validate chunk length */ chk_length = ntohs(ch->ch.chunk_length); @@ -2753,26 +2737,21 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length, sctp_service_queues(stcb, asoc); if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { - /* - * Assure that we ack right away by making sure that a d-ack - * timer is running. So the sack_check will send a sack. - */ - sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, - net); + /* Assure that we ack right away */ + stcb->asoc.send_sack = 1; } /* Start a sack timer or QUEUE a SACK for sending */ if ((stcb->asoc.cumulative_tsn == stcb->asoc.highest_tsn_inside_map) && - (stcb->asoc.first_ack_sent)) { - /* Everything is in order */ - if (stcb->asoc.mapping_array[0] == 0xff) { - /* need to do the slide */ - sctp_sack_check(stcb, 1, was_a_gap, &abort_flag); - } else { + (stcb->asoc.mapping_array[0] != 0xff)) { + if ((stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) || + (stcb->asoc.delayed_ack == 0) || + (stcb->asoc.send_sack == 1)) { if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { - stcb->asoc.first_ack_sent = 1; SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); - sctp_send_sack(stcb); - } else { + } + sctp_send_sack(stcb); + } else { + if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_start(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL); } @@ -3016,6 +2995,7 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, 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) @@ -3069,6 +3049,11 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc, (*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM; tp1->sent = SCTP_DATAGRAM_MARKED; + if (tp1->rec.data.chunk_was_revoked) { + /* deflate the cwnd */ + tp1->whoTo->cwnd -= tp1->book_size; + tp1->rec.data.chunk_was_revoked = 0; + } } break; } /* if (tp1->TSN_seq == j) */ @@ -3108,43 +3093,30 @@ sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack, */ if (tp1->sent == SCTP_DATAGRAM_ACKED) { /* it has been revoked */ + tp1->sent = SCTP_DATAGRAM_SENT; + tp1->rec.data.chunk_was_revoked = 1; + /* + * We must add this stuff back in to assure + * timers and such get started. + */ + tp1->whoTo->flight_size += tp1->book_size; + /* + * 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; - if (sctp_cmt_on_off) { - /* - * If CMT is ON, leave "sent" at - * ACKED. CMT causes reordering of - * data and acks (received on - * different interfaces) can be - * persistently reordered. Acking - * followed by apparent revoking and - * re-acking causes unexpected weird - * behavior. So, at this time, CMT - * does not respect renegs. Renegs - * cannot be recovered. I will fix - * this once I am sure that things - * are working right again with CMT. - */ - } else { - tp1->sent = SCTP_DATAGRAM_SENT; - tp1->rec.data.chunk_was_revoked = 1; - /* - * We must add this stuff back in to - * assure timers and such get - * started. - */ - tp1->whoTo->flight_size += tp1->book_size; - asoc->total_flight_count++; - asoc->total_flight += tp1->book_size; - tot_revoked++; + tot_revoked++; #ifdef SCTP_SACK_LOGGING - sctp_log_sack(asoc->last_acked_seq, - cumack, - tp1->rec.data.TSN_seq, - 0, - 0, - SCTP_LOG_TSN_REVOKED); + sctp_log_sack(asoc->last_acked_seq, + cumack, + tp1->rec.data.TSN_seq, + 0, + 0, + SCTP_LOG_TSN_REVOKED); #endif - } } else if (tp1->sent == SCTP_DATAGRAM_MARKED) { /* it has been re-acked in this SACK */ tp1->sent = SCTP_DATAGRAM_ACKED; @@ -3173,8 +3145,6 @@ sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack, } } -extern int sctp_peer_chunk_oh; - static void sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, u_long biggest_tsn_acked, u_long biggest_tsn_newly_acked, u_long this_sack_lowest_newack, int accum_moved) @@ -3301,9 +3271,11 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * the tsn... otherwise we CAN strike the TSN. */ /* - * @@@ JRI: Check for CMT + * @@@ JRI: Check for CMT if (accum_moved && + * asoc->fast_retran_loss_recovery && (sctp_cmt_on_off == + * 0)) { */ - if (accum_moved && asoc->fast_retran_loss_recovery && (sctp_cmt_on_off == 0)) { + if (accum_moved && asoc->fast_retran_loss_recovery) { /* * Strike the TSN if in fast-recovery and cum-ack * moved. @@ -3400,8 +3372,8 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, } } /* - * @@@ JRI: TODO: remove code for HTNA algo. CMT's - * SFR algo covers HTNA. + * JRI: TODO: remove code for HTNA algo. CMT's SFR + * algo covers HTNA. */ } else if (compare_with_wrap(tp1->rec.data.TSN_seq, biggest_tsn_newly_acked, MAX_TSN)) { @@ -3462,7 +3434,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc, * CMT: Using RTX_SSTHRESH policy for CMT. * If CMT is being used, then pick dest with * largest ssthresh for any retransmission. - * (iyengar@cis.udel.edu, 2005/08/12) */ tp1->no_fr_allowed = 1; alt = tp1->whoTo; @@ -3863,9 +3834,6 @@ sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net) #endif -extern int sctp_early_fr; -extern int sctp_L2_abc_variable; - static __inline void sctp_cwnd_update(struct sctp_tcb *stcb, @@ -3878,7 +3846,8 @@ sctp_cwnd_update(struct sctp_tcb *stcb, /* update cwnd and Early FR */ /******************************/ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { -#ifdef JANA_CODE_WHY_THIS + +#ifdef JANA_CMT_FAST_RECOVERY /* * CMT fast recovery code. Need to debug. */ @@ -3952,22 +3921,26 @@ sctp_cwnd_update(struct sctp_tcb *stcb, } } } -#ifdef JANA_CODE_WHY_THIS +#ifdef JANA_CMT_FAST_RECOVERY /* - * Cannot skip for CMT. Need to come back and check these - * variables for CMT. CMT fast recovery code. Need to debug. + * CMT fast recovery code + */ + /* + * if (sctp_cmt_on_off == 1 && + * net->fast_retran_loss_recovery && + * net->will_exit_fast_recovery == 0) { // @@@ Do something + * } else if (sctp_cmt_on_off == 0 && + * asoc->fast_retran_loss_recovery && will_exit == 0) { */ - if (sctp_cmt_on_off == 1 && - net->fast_retran_loss_recovery && - net->will_exit_fast_recovery == 0) #endif - if (sctp_cmt_on_off == 0 && asoc->fast_retran_loss_recovery && will_exit == 0) { - /* - * If we are in loss recovery we skip any - * cwnd update - */ - goto skip_cwnd_update; - } + + if (asoc->fast_retran_loss_recovery && will_exit == 0) { + /* + * If we are in loss recovery we skip any cwnd + * update + */ + goto skip_cwnd_update; + } /* * CMT: CUC algorithm. Update cwnd if pseudo-cumack has * moved. @@ -4172,6 +4145,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, } 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) @@ -4206,6 +4180,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, 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; } } else { @@ -4657,7 +4636,8 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, net->net_ack2 = 0; /* - * CMT: Reset CUC algo variable before SACK processing + * CMT: Reset CUC and Fast recovery algo variables before + * SACK processing */ net->new_pseudo_cumack = 0; net->will_exit_fast_recovery = 0; @@ -4775,6 +4755,11 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, (asoc->sent_queue_retran_cnt & 0x000000ff)); #endif } + 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; } } else { @@ -4919,7 +4904,7 @@ done_with_it: #endif } - if ((sctp_cmt_on_off == 0) && asoc->fast_retran_loss_recovery && accum_moved) { + if (asoc->fast_retran_loss_recovery && accum_moved) { if (compare_with_wrap(asoc->last_acked_seq, asoc->fast_recovery_tsn, MAX_TSN) || asoc->last_acked_seq == asoc->fast_recovery_tsn) { @@ -4951,6 +4936,14 @@ done_with_it: tp1->sent = SCTP_DATAGRAM_SENT; tp1->rec.data.chunk_was_revoked = 1; tp1->whoTo->flight_size += tp1->book_size; + /* + * To ensure that this increase in + * flightsize, which is artificial, + * does not throttle the sender, we + * also increase the cwnd + * artificially. + */ + tp1->whoTo->cwnd += tp1->book_size; asoc->total_flight_count++; asoc->total_flight += tp1->book_size; cnt_revoked++; @@ -5139,10 +5132,12 @@ done_with_it: } /* * CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) && - * (net->fast_retran_loss_recovery == 0))) + * (net->fast_retran_loss_recovery == 0))) if + * ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == + * 1)) { */ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { - if ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == 1)) { + if (asoc->fast_retran_loss_recovery == 0) { /* out of a RFC2582 Fast recovery window? */ if (net->net_ack > 0) { /* @@ -5287,6 +5282,9 @@ done_with_it: /* end satellite t3 loss recovery */ asoc->sat_t3_loss_recovery = 0; } + /* + * CMT Fast recovery + */ TAILQ_FOREACH(net, &asoc->nets, sctp_next) { if (net->will_exit_fast_recovery) { /* Ok, we must exit fast recovery */ |