diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 65eb08642f5..243d773723d 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -46,24 +46,13 @@ __FBSDID("$FreeBSD$"); #include #define SCTP_CALC_TSN_TO_GAP(gap, tsn, mapping_tsn) do { \ - if ((compare_with_wrap(tsn, mapping_tsn, MAX_TSN)) || \ - (tsn == mapping_tsn)) { \ + if (tsn >= mapping_tsn) { \ gap = tsn - mapping_tsn; \ } else { \ gap = (MAX_TSN - mapping_tsn) + tsn + 1; \ } \ } while(0) -#define SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc) do { \ - if (asoc->mapping_array_base_tsn == asoc->nr_mapping_array_base_tsn) { \ - SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, nr_gap); \ - } else {\ - int lgap; \ - SCTP_CALC_TSN_TO_GAP(lgap, tsn, asoc->mapping_array_base_tsn); \ - SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, lgap); \ - } \ - } while(0) - /* * 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 @@ -304,6 +293,44 @@ sctp_build_ctl_cchunk(struct sctp_inpcb *inp, return (buf); } +static void +sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn) +{ + uint32_t gap, i; + int fnd = 0; + + if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { + return; + } + SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); +#ifdef INVARIANTS + if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { + printf("gap:%x tsn:%x\n", gap, tsn); + sctp_print_mapping_array(asoc); + panic("Things are really messed up now!!"); + } +#endif + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } + if (tsn == asoc->highest_tsn_inside_map) { + /* We must back down to see what the new highest is */ + for (i = tsn - 1; compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN); i--) { + SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); + if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { + asoc->highest_tsn_inside_map = i; + fnd = 1; + break; + } + } + if (!fnd) { + asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1; + } + } +} + /* * We are delivering currently from the reassembly queue. We must continue to @@ -319,9 +346,6 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc) int end = 0; int cntDel; - /* EY if any out-of-order delivered, then tag it nr on nr_map */ - uint32_t nr_tsn, nr_gap; - struct sctp_queued_to_read *control, *ctl, *ctlat; if (stcb == NULL) @@ -430,39 +454,7 @@ abandon: } /* pull it we did it */ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); - /* - * EY this is the chunk that should be tagged nr gapped - * calculate the gap and such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - /* - * EY!-TODO- this tsn should be tagged nr only if it is - * out-of-order, the if statement should be modified - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - nr_tsn = chk->rec.data.TSN_seq; - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY The 1st should never happen, as in - * process_a_data_chunk method this check - * should be done - */ - /* - * EY The 2nd should never happen, because - * nr_mapping_array is always expanded when - * mapping_array is expanded - */ - printf("Impossible nr_gap ack range failed\n"); - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { asoc->fragmented_delivery_inprogress = 0; if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) { @@ -509,67 +501,11 @@ abandon: asoc->size_on_all_streams -= ctl->length; sctp_ucount_decr(asoc->cnt_on_all_streams); strm->last_sequence_delivered++; - /* - * EY will be used to - * calculate nr-gap - */ - nr_tsn = ctl->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, ctl, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY -now something is - * delivered, calculate - * nr_gap and tag this tsn - * NR - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY The - * 1st - * should - * never - * happen, - * as in - * process_a_ - * data_chunk - * method - * this - * check - * should be - * done - */ - /* - * EY The - * 2nd - * should - * never - * happen, - * because - * nr_mapping - * _array is - * always - * expanded - * when - * mapping_ar - * ray is - * expanded - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, - asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); ctl = ctlat; } else { break; @@ -618,9 +554,6 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc, uint16_t nxt_todel; struct mbuf *oper; - /* EY- will be used to calculate nr-gap for a tsn */ - uint32_t nr_tsn, nr_gap; - queue_needed = 1; asoc->size_on_all_streams += control->length; sctp_ucount_incr(asoc->cnt_on_all_streams); @@ -682,41 +615,12 @@ protocol_error: asoc->size_on_all_streams -= control->length; sctp_ucount_decr(asoc->cnt_on_all_streams); strm->last_sequence_delivered++; - /* EY will be used to calculate nr-gap */ - nr_tsn = control->sinfo_tsn; + sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be tagged nr gapped - * calculate the gap and such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - printf("Impossible nr_tsn set 2?\n"); - /* - * EY The 1st should never happen, as in - * process_a_data_chunk method this check - * should be done - */ - /* - * EY The 2nd should never happen, because - * nr_mapping_array is always expanded when - * mapping_array is expanded - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, control->sinfo_tsn); control = TAILQ_FIRST(&strm->inqueue); while (control != NULL) { /* all delivered */ @@ -738,47 +642,12 @@ protocol_error: SCTP_STR_LOG_FROM_IMMED_DEL); } /* EY will be used to calculate nr-gap */ - nr_tsn = control->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be - * tagged nr gapped calculate the gap and - * such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY The 1st should never - * happen, as in - * process_a_data_chunk - * method this check should - * be done - */ - /* - * EY The 2nd should never - * happen, because - * nr_mapping_array is - * always expanded when - * mapping_array is expanded - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - if (compare_with_wrap(nr_tsn, - asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - } + sctp_mark_non_revokable(asoc, control->sinfo_tsn); control = at; continue; } @@ -1586,9 +1455,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, /* struct sctp_tmit_chunk *chk; */ struct sctp_tmit_chunk *chk; uint32_t tsn, gap; - - /* EY - for nr_sack */ - uint32_t nr_gap; struct mbuf *dmbuf; int indx, the_len; int need_reasm_check = 0; @@ -1640,14 +1506,12 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, return (0); } } - /* EY - for nr_sack */ - nr_gap = gap; - if (compare_with_wrap(tsn, *high_tsn, MAX_TSN)) { *high_tsn = tsn; } /* See if we have received this one already */ - if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { + if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap) || + SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, gap)) { SCTP_STAT_INCR(sctps_recvdupdata); if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) { /* Record a dup for the next outbound sack */ @@ -1714,7 +1578,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, #endif } /* now is it in the mapping array of what we have accepted? */ - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN) && + compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { /* Nope not in the valid range dump it */ sctp_set_rwnd(stcb, asoc); if ((asoc->cnt_on_all_streams + @@ -1758,23 +1623,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, } SCTP_STAT_INCR(sctps_badsid); SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); - /* EY set this tsn present in nr_sack's nr_mapping_array */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); - SCTP_REVERSE_OUT_TSN_PRES(gap, tsn, asoc); - } - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { - /* we have a new high score */ - asoc->highest_tsn_inside_map = tsn; - /* EY nr_sack version of the above */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) - asoc->highest_tsn_inside_nr_map = tsn; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 2, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } + + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; } if (tsn == (asoc->cumulative_tsn + 1)) { /* Update cum-ack */ @@ -1925,48 +1777,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY here I should check if this delivered tsn is - * out_of_order, if yes then update the nr_map - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - /* - * EY check if the mapping_array and nr_mapping - * array are consistent - */ - if (asoc->mapping_array_base_tsn != asoc->nr_mapping_array_base_tsn) - /* - * printf("EY-IN - * sctp_process_a_data_chunk(5): Something - * is wrong the map base tsn" "\nEY-and - * nr_map base tsn should be equal."); - */ - /* EY debugging block */ - { - /* - * printf("\nEY-Calculating an - * nr_gap!!\nmapping_array_size = %d - * nr_mapping_array_size = %d" - * "\nEY-mapping_array_base = %d - * nr_mapping_array_base = - * %d\nEY-highest_tsn_inside_map = %d" - * "highest_tsn_inside_nr_map = %d\nEY-TSN = - * %d nr_gap = %d",asoc->mapping_array_size, - * asoc->nr_mapping_array_size, - * asoc->mapping_array_base_tsn, - * asoc->nr_mapping_array_base_tsn, - * asoc->highest_tsn_inside_map, - * asoc->highest_tsn_inside_nr_map,tsn,nr_gap - * ); - */ - } - /* EY - not %100 sure about the lock thing */ - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = tsn; - } if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) { /* for ordered, bump what we delivered */ asoc->strmin[strmno].last_sequence_delivered++; @@ -1977,6 +1787,10 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, SCTP_STR_LOG_FROM_EXPRS_DEL); } control = NULL; + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } goto finish_express_del; } failed_express_del: @@ -2012,39 +1826,9 @@ failed_express_del: SCTP_PRINTF("Append fails end:%d\n", end); goto failed_pdapi_express_del; } - /* - * EY It is appended to the read queue in prev if - * block here I should check if this delivered tsn - * is out_of_order, if yes then update the nr_map - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - /* EY debugging block */ - { - /* - * printf("\nEY-Calculating an - * nr_gap!!\nEY-mapping_array_size = - * %d nr_mapping_array_size = %d" - * "\nEY-mapping_array_base = %d - * nr_mapping_array_base = - * %d\nEY-highest_tsn_inside_map = - * %d" "highest_tsn_inside_nr_map = - * %d\nEY-TSN = %d nr_gap = - * %d",asoc->mapping_array_size, - * asoc->nr_mapping_array_size, - * asoc->mapping_array_base_tsn, - * asoc->nr_mapping_array_base_tsn, - * asoc->highest_tsn_inside_map, - * asoc->highest_tsn_inside_nr_map,ts - * n,nr_gap); - */ - } - /* EY - not %100 sure about the lock thing */ - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = tsn; + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; } SCTP_STAT_INCR(sctps_recvexpressm); control->sinfo_tsn = tsn; @@ -2069,12 +1853,27 @@ failed_express_del: need_reasm_check = 1; } } + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } control = NULL; goto finish_express_del; } } failed_pdapi_express_del: control = NULL; + if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + asoc->highest_tsn_inside_nr_map = tsn; + } + } else { + SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); + if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { + asoc->highest_tsn_inside_map = tsn; + } + } if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) { sctp_alloc_a_chunk(stcb, chk); if (chk == NULL) { @@ -2263,56 +2062,7 @@ failed_pdapi_express_del: sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY It is added to the read queue in prev if block - * here I should check if this delivered tsn is - * out_of_order, if yes then update the nr_map - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - /* - * EY check if the mapping_array and - * nr_mapping array are consistent - */ - if (asoc->mapping_array_base_tsn != asoc->nr_mapping_array_base_tsn) - /* - * printf("EY-IN - * sctp_process_a_data_chunk(6): - * Something is wrong the map base - * tsn" "\nEY-and nr_map base tsn - * should be equal."); - */ - /* - * EY - not %100 sure about the lock - * thing, i think we don't need the - * below, - */ - /* SCTP_TCB_LOCK_ASSERT(stcb); */ - { - /* - * printf("\nEY-Calculating an - * nr_gap!!\nEY-mapping_array_size = - * %d nr_mapping_array_size = %d" - * "\nEY-mapping_array_base = %d - * nr_mapping_array_base = - * %d\nEY-highest_tsn_inside_map = - * %d" "highest_tsn_inside_nr_map = - * %d\nEY-TSN = %d nr_gap = - * %d",asoc->mapping_array_size, - * asoc->nr_mapping_array_size, - * asoc->mapping_array_base_tsn, - * asoc->nr_mapping_array_base_tsn, - * asoc->highest_tsn_inside_map, - * asoc->highest_tsn_inside_nr_map,ts - * n,nr_gap); - */ - } - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) - asoc->highest_tsn_inside_nr_map = tsn; - } + } else { /* * Special check for when streams are resetting. We @@ -2384,13 +2134,6 @@ failed_pdapi_express_del: } } finish_express_del: - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { - /* we have a new high score */ - asoc->highest_tsn_inside_map = tsn; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 2, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } - } if (tsn == (asoc->cumulative_tsn + 1)) { /* Update cum-ack */ asoc->cumulative_tsn = tsn; @@ -2412,22 +2155,6 @@ finish_express_del: sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE); } - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap); - - /* - * EY - set tsn present in nr-map if doing nr-sacks and the tsn is - * non-renegable - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack && - (SCTP_BASE_SYSCTL(sctp_do_drain) == 0)) { - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, tsn, asoc); - if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { - asoc->highest_tsn_inside_nr_map = tsn; - } - } /* check the special flag for stream resets */ if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) && ((compare_with_wrap(asoc->cumulative_tsn, liste->tsn, MAX_TSN)) || @@ -2532,7 +2259,6 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort */ struct sctp_association *asoc; int at; - uint8_t comb_byte; int last_all_ones = 0; int slide_from, slide_end, lgap, distance; @@ -2540,7 +2266,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort /* int nr_at; */ /* int nr_last_all_ones = 0; */ /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */ - uint32_t old_cumack, old_base, old_highest; + uint32_t old_cumack, old_base, old_highest, highest_tsn; asoc = &stcb->asoc; at = 0; @@ -2553,30 +2279,23 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort * offset of the current cum-ack as the starting point. */ at = 0; - for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { - /* - * We must combine the renegable and non-renegable arrays - * here to form a unified view of what is acked right now - * (since they are kept separate - */ - comb_byte = asoc->mapping_array[slide_from] | asoc->nr_mapping_array[slide_from]; - if (comb_byte == 0xff) { + for (slide_from = 0; slide_from < stcb->asoc.nr_mapping_array_size; slide_from++) { + if (asoc->nr_mapping_array[slide_from] == 0xff) { at += 8; last_all_ones = 1; } else { /* there is a 0 bit */ - at += sctp_map_lookup_tab[comb_byte]; + at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]]; last_all_ones = 0; break; } } - asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at - last_all_ones); - /* at is one off, since in the table a embedded -1 is present */ + asoc->cumulative_tsn = asoc->nr_mapping_array_base_tsn + (at - last_all_ones); at++; - if (compare_with_wrap(asoc->cumulative_tsn, - asoc->highest_tsn_inside_map, - MAX_TSN)) { + if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) && + compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN) + ) { #ifdef INVARIANTS panic("huh, cumack 0x%x greater than high-tsn 0x%x in map", asoc->cumulative_tsn, asoc->highest_tsn_inside_map); @@ -2591,37 +2310,29 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn; #endif } - if ((asoc->cumulative_tsn == asoc->highest_tsn_inside_map) && (at >= 8)) { + if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, + asoc->highest_tsn_inside_map, + MAX_TSN)) { + highest_tsn = asoc->highest_tsn_inside_nr_map; + } else { + highest_tsn = asoc->highest_tsn_inside_map; + } + if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) { /* The complete array was completed by a single FR */ - /* higest becomes the cum-ack */ + /* highest becomes the cum-ack */ int clr; - asoc->cumulative_tsn = asoc->highest_tsn_inside_map; /* clear the array */ clr = (at >> 3) + 1; if (clr > asoc->mapping_array_size) { clr = asoc->mapping_array_size; } memset(asoc->mapping_array, 0, clr); - /* base becomes one ahead of the cum-ack */ + memset(asoc->nr_mapping_array, 0, clr); + asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1; - - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - - if (clr > asoc->nr_mapping_array_size) - clr = asoc->nr_mapping_array_size; - - memset(asoc->nr_mapping_array, 0, clr); - /* base becomes one ahead of the cum-ack */ - asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1; - asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn; - } - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(old_base, old_cumack, old_highest, - SCTP_MAP_PREPARE_SLIDE); - sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, - asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_CLEARED); - } + asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1; + asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn; } else if (at >= 8) { /* we can slide the mapping array down */ /* slide_from holds where we hit the first NON 0xff byte */ @@ -2630,19 +2341,15 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort * now calculate the ceiling of the move using our highest * TSN value */ - if (asoc->highest_tsn_inside_map >= asoc->mapping_array_base_tsn) { - lgap = asoc->highest_tsn_inside_map - - asoc->mapping_array_base_tsn; - } else { - lgap = (MAX_TSN - asoc->mapping_array_base_tsn) + - asoc->highest_tsn_inside_map + 1; - } - slide_end = lgap >> 3; + SCTP_CALC_TSN_TO_GAP(lgap, highest_tsn, asoc->mapping_array_base_tsn); + slide_end = (lgap >> 3); if (slide_end < slide_from) { + sctp_print_mapping_array(asoc); #ifdef INVARIANTS panic("impossible slide"); #else - printf("impossible slide?\n"); + printf("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n", + lgap, slide_end, slide_from, at); return; #endif } @@ -2682,30 +2389,21 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort for (ii = 0; ii < distance; ii++) { asoc->mapping_array[ii] = asoc->mapping_array[slide_from + ii]; + asoc->nr_mapping_array[ii] = + asoc->nr_mapping_array[slide_from + ii]; + } for (ii = distance; ii <= slide_end; ii++) { asoc->mapping_array[ii] = 0; + asoc->nr_mapping_array[ii] = 0; } asoc->mapping_array_base_tsn += (slide_from << 3); + asoc->nr_mapping_array_base_tsn += (slide_from << 3); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); } - /* - * EY if doing nr_sacks then slide the - * nr_mapping_array accordingly please - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - for (ii = 0; ii < distance; ii++) { - asoc->nr_mapping_array[ii] = - asoc->nr_mapping_array[slide_from + ii]; - } - for (ii = distance; ii <= slide_end; ii++) { - asoc->nr_mapping_array[ii] = 0; - } - asoc->nr_mapping_array_base_tsn += (slide_from << 3); - } } } /* @@ -2736,8 +2434,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort int is_a_gap; /* is there a gap now ? */ - is_a_gap = compare_with_wrap(stcb->asoc.highest_tsn_inside_map, - stcb->asoc.cumulative_tsn, MAX_TSN); + is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN); /* * CMT DAC algorithm: increase number of packets @@ -5742,9 +5439,6 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, struct sctp_association *asoc; int tt; - /* EY -used to calculate nr_gap information */ - uint32_t nr_tsn, nr_gap; - asoc = &stcb->asoc; tt = strmin->last_sequence_delivered; /* @@ -5764,82 +5458,10 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, /* deliver it to at least the delivery-q */ if (stcb->sctp_socket) { /* EY need the tsn info for calculating nr */ - nr_tsn = ctl->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, ctl, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be - * tagged nr gapped calculate the gap and - * such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY These should never - * happen- explained before - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, - asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, nr_gap)) - /* - * printf("In - * sctp_kick_prsctp_reorder_q - * ueue(7): Something wrong, - * the TSN to be tagged" - * "\nas NR is not even in - * the mapping_array, or map - * and nr_map are - * inconsistent"); - */ - /* - * EY - not %100 sure about - * the lock thing, don't - * think its required - */ - /* - * SCTP_TCB_LOCK_ASSERT(stcb) - * ; - */ - { - /* - * printf("\nCalculating an - * nr_gap!!\nmapping_array_si - * ze = %d - * nr_mapping_array_size = - * %d" "\nmapping_array_base - * = %d - * nr_mapping_array_base = - * %d\nhighest_tsn_inside_map - * = %d" - * "highest_tsn_inside_nr_map - * = %d\nTSN = %d nr_gap = - * %d",asoc->mapping_array_si - * ze, - * asoc->nr_mapping_array_siz - * e, - * asoc->mapping_array_base_t - * sn, - * asoc->nr_mapping_array_bas - * e_tsn, - * asoc->highest_tsn_inside_m - * ap, - * asoc->highest_tsn_inside_n - * r_map,tsn,nr_gap); - */ - } - } + sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); } } else { /* no more delivery now. */ @@ -5864,82 +5486,11 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb, /* deliver it to at least the delivery-q */ strmin->last_sequence_delivered = ctl->sinfo_ssn; if (stcb->sctp_socket) { - /* EY */ - nr_tsn = ctl->sinfo_tsn; sctp_add_to_readq(stcb->sctp_ep, stcb, ctl, &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); - /* - * EY this is the chunk that should be - * tagged nr gapped calculate the gap and - * such then tag this TSN nr - * chk->rec.data.TSN_seq - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - asoc->peer_supports_nr_sack) { - SCTP_CALC_TSN_TO_GAP(nr_gap, nr_tsn, asoc->nr_mapping_array_base_tsn); - if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) || - (nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) { - /* - * EY These should never - * happen, explained before - */ - } else { - SCTP_TCB_LOCK_ASSERT(stcb); - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap); - SCTP_REVERSE_OUT_TSN_PRES(nr_gap, nr_tsn, asoc); - if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, - MAX_TSN)) - asoc->highest_tsn_inside_nr_map = nr_tsn; - } - if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, nr_gap)) - /* - * printf("In - * sctp_kick_prsctp_reorder_q - * ueue(8): Something wrong, - * the TSN to be tagged" - * "\nas NR is not even in - * the mapping_array, or map - * and nr_map are - * inconsistent"); - */ - /* - * EY - not %100 sure about - * the lock thing, don't - * think its required - */ - /* - * SCTP_TCB_LOCK_ASSERT(stcb) - * ; - */ - { - /* - * printf("\nCalculating an - * nr_gap!!\nmapping_array_si - * ze = %d - * nr_mapping_array_size = - * %d" "\nmapping_array_base - * = %d - * nr_mapping_array_base = - * %d\nhighest_tsn_inside_map - * = %d" - * "highest_tsn_inside_nr_map - * = %d\nTSN = %d nr_gap = - * %d",asoc->mapping_array_si - * ze, - * asoc->nr_mapping_array_siz - * e, - * asoc->mapping_array_base_t - * sn, - * asoc->nr_mapping_array_bas - * e_tsn, - * asoc->highest_tsn_inside_m - * ap, - * asoc->highest_tsn_inside_n - * r_map,tsn,nr_gap); - */ - } - } + sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); + } tt = strmin->last_sequence_delivered + 1; } else { @@ -6096,25 +5647,19 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map, MAX_TSN)) { asoc->highest_tsn_inside_map = new_cum_tsn; - /* EY nr_mapping_array version of the above */ - /* - * if(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && - * asoc->peer_supports_nr_sack) - */ + + } + if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, + MAX_TSN)) { asoc->highest_tsn_inside_nr_map = new_cum_tsn; - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } } /* * now we know the new TSN is more advanced, let's find the actual * gap */ - SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn); + SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->nr_mapping_array_base_tsn); + asoc->cumulative_tsn = new_cum_tsn; if (gap >= m_size) { - if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { - sctp_log_map(0, 0, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); - } if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) { struct mbuf *oper; @@ -6147,23 +5692,15 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, return; } SCTP_STAT_INCR(sctps_fwdtsn_map_over); + memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - cumack_set_flag = 1; asoc->mapping_array_base_tsn = new_cum_tsn + 1; - asoc->cumulative_tsn = asoc->highest_tsn_inside_map = new_cum_tsn; - /* EY - nr_sack: nr_mapping_array version of the above */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) { - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); - asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1; - asoc->highest_tsn_inside_nr_map = new_cum_tsn; - if (asoc->nr_mapping_array_size != asoc->mapping_array_size) { - /* - * printf("IN sctp_handle_forward_tsn: - * Something is wrong the size of" "map and - * nr_map should be equal!") - */ ; - } - } + asoc->highest_tsn_inside_map = new_cum_tsn; + + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); + asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1; + asoc->highest_tsn_inside_nr_map = new_cum_tsn; + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); } @@ -6171,12 +5708,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb, } else { SCTP_TCB_LOCK_ASSERT(stcb); for (i = 0; i <= gap; i++) { - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack - && SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { - SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); - } else { - SCTP_SET_TSN_PRESENT(asoc->mapping_array, i); - } + SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, i); + SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); } /* * Now after marking all, slide thing forward but no sack diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index ef187377b95..07518e42cf9 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -1860,9 +1860,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, memset(asoc->mapping_array, 0, asoc->mapping_array_size); } - /* EY 05/13/08 - nr_sack version of the above if statement */ - if (asoc->nr_mapping_array && SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) - && asoc->peer_supports_nr_sack) { + if (asoc->nr_mapping_array) { memset(asoc->nr_mapping_array, 0, asoc->nr_mapping_array_size); } @@ -3515,16 +3513,10 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - /* - * EY 05/13/08 - nr_sack: to keep - * nr_mapping array be consistent - * with mapping_array - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) { - stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; - stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.mapping_array_base_tsn; - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); - } + stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; + stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.mapping_array_base_tsn; + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); + stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; @@ -3631,15 +3623,9 @@ sctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; stcb->asoc.mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); - /* - * EY 05/13/08 -nr_sack: to keep nr_mapping array consistent - * with mapping array - */ - if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) { - stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; - stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; - memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); - } + stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; + stcb->asoc.nr_mapping_array_base_tsn = stcb->asoc.highest_tsn_inside_map + 1; + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); atomic_add_int(&stcb->asoc.sending_seq, 1); /* save off historical data for retrans */ stcb->asoc.last_sending_seq[1] = stcb->asoc.last_sending_seq[0]; diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index be4c3a8633f..b3e5781ff52 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -7871,19 +7871,8 @@ again_one_more_time: pf_hbflag = 1; } /* remove these chunks at the end */ - if (chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) { - /* turn off the timer */ - if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { - sctp_timer_stop(SCTP_TIMER_TYPE_RECV, - inp, stcb, net, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_1); - } - } - /* - * EY -Nr-sack version of the above - * if statement - */ - if ((SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) && - (chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK)) { /* EY !?! */ + if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) || + (chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK)) { /* turn off the timer */ if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { sctp_timer_stop(SCTP_TIMER_TYPE_RECV, @@ -9885,6 +9874,7 @@ sctp_send_sack(struct sctp_tcb *stcb) unsigned int num_gap_blocks = 0, space; int num_dups = 0; int space_req; + uint32_t highest_tsn; a_chk = NULL; asoc = &stcb->asoc; @@ -9970,7 +9960,12 @@ sctp_send_sack(struct sctp_tcb *stcb) if (a_chk->whoTo) { atomic_add_int(&a_chk->whoTo->ref_count, 1); } - if (asoc->highest_tsn_inside_map == asoc->cumulative_tsn) { + if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + highest_tsn = asoc->highest_tsn_inside_map; + } else { + highest_tsn = asoc->highest_tsn_inside_nr_map; + } + if (highest_tsn == asoc->cumulative_tsn) { /* no gaps */ space_req = sizeof(struct sctp_sack_chunk); } else { @@ -10043,10 +10038,10 @@ sctp_send_sack(struct sctp_tcb *stcb) gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk)); - if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn) - siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8; + if (highest_tsn > asoc->mapping_array_base_tsn) + siz = (((highest_tsn - asoc->mapping_array_base_tsn) + 1) + 7) / 8; else - siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8; + siz = (((MAX_TSN - highest_tsn) + 1) + highest_tsn + 7) / 8; if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) { offset = 1; @@ -10063,10 +10058,10 @@ sctp_send_sack(struct sctp_tcb *stcb) */ jstart = 1; } - if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN)) { + if (compare_with_wrap(highest_tsn, asoc->cumulative_tsn, MAX_TSN)) { /* we have a gap .. maybe */ for (i = 0; i < siz; i++) { - selector = &sack_array[asoc->mapping_array[i]]; + selector = &sack_array[(asoc->mapping_array[i] | asoc->nr_mapping_array[i])]; if (mergeable && selector->right_edge) { /* * Backup, left and right edges were ok to @@ -10120,8 +10115,6 @@ sctp_send_sack(struct sctp_tcb *stcb) */ int abort_flag = 0; - asoc->cumulative_tsn = asoc->highest_tsn_inside_map; - sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn); sctp_sack_check(stcb, 0, 0, &abort_flag); } } @@ -10180,13 +10173,13 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) int mergeable = 0; int offset; caddr_t limit; - uint32_t *dup; + uint32_t *dup, highest_tsn; int limit_reached = 0; + int seen_non_zero = 0; unsigned int i, jstart, siz, j; unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space; int num_dups = 0; int space_req; - unsigned int reserved = 0; a_chk = NULL; asoc = &stcb->asoc; @@ -10272,7 +10265,12 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) if (a_chk->whoTo) { atomic_add_int(&a_chk->whoTo->ref_count, 1); } - if (asoc->highest_tsn_inside_map == asoc->cumulative_tsn) { + if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { + highest_tsn = asoc->highest_tsn_inside_map; + } else { + highest_tsn = asoc->highest_tsn_inside_nr_map; + } + if (highest_tsn == asoc->cumulative_tsn) { /* no gaps */ space_req = sizeof(struct sctp_nr_sack_chunk); } else { @@ -10371,6 +10369,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN)) { /* we have a gap .. maybe */ for (i = 0; i < siz; i++) { + seen_non_zero = 1; selector = &sack_array[asoc->mapping_array[i]]; if (mergeable && selector->right_edge) { /* @@ -10418,22 +10417,8 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) jstart = 0; offset += 8; } - if (num_gap_blocks == 0) { - /* - * slide not yet happened, and somehow we got called - * to send a sack. Cumack needs to move up. - */ - int abort_flag = 0; - - asoc->cumulative_tsn = asoc->highest_tsn_inside_map; - nr_sack->nr_sack.cum_tsn_ack = htonl(asoc->cumulative_tsn); - sctp_sack_check(stcb, 0, 0, &abort_flag); - } } - /*---------------------------------------------------------filling the nr_gap_ack blocks----------------------------------------------------*/ - - /* EY - there will be gaps + nr_gaps if draining is possible */ - if ((SCTP_BASE_SYSCTL(sctp_do_drain)) && (limit_reached == 0)) { + if (limit_reached == 0) { mergeable = 0; @@ -10510,9 +10495,6 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) } } } - /*---------------------------------------------End of---filling the nr_gap_ack blocks----------------------------------------------------*/ - - /* now we must add any dups we are going to report. */ if ((limit_reached == 0) && (asoc->numduptsns)) { dup = (uint32_t *) gap_descriptor; for (i = 0; i < asoc->numduptsns; i++) { @@ -10530,10 +10512,6 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) * now that the chunk is prepared queue it to the control chunk * queue. */ - if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { - num_nr_gap_blocks = num_gap_blocks; - num_gap_blocks = 0; - } a_chk->send_size = sizeof(struct sctp_nr_sack_chunk) + (num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) + num_dups * sizeof(int32_t); @@ -10542,7 +10520,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb) nr_sack->nr_sack.num_gap_ack_blks = htons(num_gap_blocks); nr_sack->nr_sack.num_nr_gap_ack_blks = htons(num_nr_gap_blocks); nr_sack->nr_sack.num_dup_tsns = htons(num_dups); - nr_sack->nr_sack.reserved = htons(reserved); + nr_sack->nr_sack.reserved = 0; nr_sack->ch.chunk_length = htons(a_chk->send_size); TAILQ_INSERT_TAIL(&asoc->control_send_queue, a_chk, sctp_next); asoc->ctrl_queue_cnt++; diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index c03b9d0e245..e9f5aecb998 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -1175,7 +1175,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, asoc->discontinuity_time = asoc->start_time; /* * sa_ignore MEMLEAK {memory is put in the assoc mapping array and - * freed later whe the association is freed. + * freed later when the association is freed. */ return (0); } @@ -1183,7 +1183,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb, void sctp_print_mapping_array(struct sctp_association *asoc) { - int i; + int i, limit; printf("Mapping size:%d baseTSN:%8.8x cumAck:%8.8x highestTSN:%8.8x\n", asoc->mapping_array_size, @@ -1191,9 +1191,39 @@ sctp_print_mapping_array(struct sctp_association *asoc) asoc->cumulative_tsn, asoc->highest_tsn_inside_map ); - for (i = 0; i < asoc->mapping_array_size; i++) { - printf("%8.8x ", asoc->mapping_array[i]); - if (((i + 1) % 8) == 0) + limit = asoc->mapping_array_size; + for (i = asoc->mapping_array_size; i >= 0; i--) { + if (asoc->mapping_array[i]) { + limit = i; + break; + } + } + if (limit == 0) + limit = 1; + for (i = 0; i < limit; i++) { + printf("%2.2x ", asoc->mapping_array[i]); + if (((i + 1) % 16) == 0) + printf("\n"); + } + printf("\n"); + printf("NR Mapping size:%d baseTSN:%8.8x highestTSN:%8.8x\n", + asoc->nr_mapping_array_size, + asoc->nr_mapping_array_base_tsn, + asoc->highest_tsn_inside_nr_map + ); + limit = asoc->nr_mapping_array_size; + for (i = asoc->nr_mapping_array_size; i >= 0; i--) { + if (asoc->nr_mapping_array[i]) { + limit = i; + break; + } + } + if (limit == 0) + limit = 1; + + for (i = 0; i < limit; i++) { + printf("%2.2x ", asoc->nr_mapping_array[i]); + if (((i + 1) % 16) == 0) printf("\n"); } printf("\n");