sctp_indata.c (205627) | sctp_indata.c (206137) |
---|---|
1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * a) Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. --- 17 unchanged lines hidden (view full) --- 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* $KAME: sctp_indata.c,v 1.36 2005/03/06 16:04:17 itojun Exp $ */ 32 33#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * a) Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. --- 17 unchanged lines hidden (view full) --- 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31/* $KAME: sctp_indata.c,v 1.36 2005/03/06 16:04:17 itojun Exp $ */ 32 33#include <sys/cdefs.h> |
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 205627 2010-03-24 19:45:36Z rrs $"); | 34__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 206137 2010-04-03 15:40:14Z tuexen $"); |
35 36#include <netinet/sctp_os.h> 37#include <netinet/sctp_var.h> 38#include <netinet/sctp_sysctl.h> 39#include <netinet/sctp_pcb.h> 40#include <netinet/sctp_header.h> 41#include <netinet/sctputil.h> 42#include <netinet/sctp_output.h> 43#include <netinet/sctp_input.h> 44#include <netinet/sctp_indata.h> 45#include <netinet/sctp_uio.h> 46#include <netinet/sctp_timer.h> 47 | 35 36#include <netinet/sctp_os.h> 37#include <netinet/sctp_var.h> 38#include <netinet/sctp_sysctl.h> 39#include <netinet/sctp_pcb.h> 40#include <netinet/sctp_header.h> 41#include <netinet/sctputil.h> 42#include <netinet/sctp_output.h> 43#include <netinet/sctp_input.h> 44#include <netinet/sctp_indata.h> 45#include <netinet/sctp_uio.h> 46#include <netinet/sctp_timer.h> 47 |
48#define SCTP_CALC_TSN_TO_GAP(gap, tsn, mapping_tsn) do { \ 49 if (tsn >= mapping_tsn) { \ 50 gap = tsn - mapping_tsn; \ 51 } else { \ 52 gap = (MAX_TSN - mapping_tsn) + tsn + 1; \ 53 } \ 54 } while(0) | |
55 56/* 57 * NOTES: On the outbound side of things I need to check the sack timer to 58 * see if I should generate a sack into the chunk queue (if I have data to 59 * send that is and will be sending it .. for bundling. 60 * 61 * The callback in sctp_usrreq.c will get called when the socket is read from. 62 * This will cause sctp_service_queues() to get called on the top entry in --- 235 unchanged lines hidden (view full) --- 298{ 299 uint32_t gap, i; 300 int fnd = 0; 301 302 if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 303 return; 304 } 305 SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); | 48 49/* 50 * NOTES: On the outbound side of things I need to check the sack timer to 51 * see if I should generate a sack into the chunk queue (if I have data to 52 * send that is and will be sending it .. for bundling. 53 * 54 * The callback in sctp_usrreq.c will get called when the socket is read from. 55 * This will cause sctp_service_queues() to get called on the top entry in --- 235 unchanged lines hidden (view full) --- 291{ 292 uint32_t gap, i; 293 int fnd = 0; 294 295 if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 296 return; 297 } 298 SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); |
306#ifdef INVARIANTS | |
307 if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 308 printf("gap:%x tsn:%x\n", gap, tsn); 309 sctp_print_mapping_array(asoc); | 299 if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 300 printf("gap:%x tsn:%x\n", gap, tsn); 301 sctp_print_mapping_array(asoc); |
302#ifdef INVARIANTS |
|
310 panic("Things are really messed up now!!"); | 303 panic("Things are really messed up now!!"); |
311 } | |
312#endif | 304#endif |
305 } |
|
313 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 314 SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 315 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 316 asoc->highest_tsn_inside_nr_map = tsn; 317 } 318 if (tsn == asoc->highest_tsn_inside_map) { 319 /* We must back down to see what the new highest is */ | 306 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 307 SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 308 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 309 asoc->highest_tsn_inside_nr_map = tsn; 310 } 311 if (tsn == asoc->highest_tsn_inside_map) { 312 /* We must back down to see what the new highest is */ |
320 for (i = tsn - 1; compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN); i--) { | 313 for (i = tsn - 1; (compare_with_wrap(i, asoc->mapping_array_base_tsn, MAX_TSN) || 314 (i == asoc->mapping_array_base_tsn)); i--) { |
321 SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); 322 if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 323 asoc->highest_tsn_inside_map = i; 324 fnd = 1; 325 break; 326 } 327 } 328 if (!fnd) { --- 77 unchanged lines hidden (view full) --- 406 return; 407 } 408 /* save it off for our future deliveries */ 409 stcb->asoc.control_pdapi = control; 410 if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) 411 end = 1; 412 else 413 end = 0; | 315 SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); 316 if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 317 asoc->highest_tsn_inside_map = i; 318 fnd = 1; 319 break; 320 } 321 } 322 if (!fnd) { --- 77 unchanged lines hidden (view full) --- 400 return; 401 } 402 /* save it off for our future deliveries */ 403 stcb->asoc.control_pdapi = control; 404 if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) 405 end = 1; 406 else 407 end = 0; |
408 sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); |
|
414 sctp_add_to_readq(stcb->sctp_ep, 415 stcb, control, &stcb->sctp_socket->so_rcv, end, 416 SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 417 cntDel++; 418 } else { 419 if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) 420 end = 1; 421 else 422 end = 0; | 409 sctp_add_to_readq(stcb->sctp_ep, 410 stcb, control, &stcb->sctp_socket->so_rcv, end, 411 SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 412 cntDel++; 413 } else { 414 if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) 415 end = 1; 416 else 417 end = 0; |
418 sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); |
|
423 if (sctp_append_to_readq(stcb->sctp_ep, stcb, 424 stcb->asoc.control_pdapi, 425 chk->data, end, chk->rec.data.TSN_seq, 426 &stcb->sctp_socket->so_rcv)) { 427 /* 428 * something is very wrong, either 429 * control_pdapi is NULL, or the tail_mbuf 430 * is corrupt, or there is a EOM already on --- 18 unchanged lines hidden (view full) --- 449#endif 450 goto abandon; 451 } 452 } 453 cntDel++; 454 } 455 /* pull it we did it */ 456 TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); | 419 if (sctp_append_to_readq(stcb->sctp_ep, stcb, 420 stcb->asoc.control_pdapi, 421 chk->data, end, chk->rec.data.TSN_seq, 422 &stcb->sctp_socket->so_rcv)) { 423 /* 424 * something is very wrong, either 425 * control_pdapi is NULL, or the tail_mbuf 426 * is corrupt, or there is a EOM already on --- 18 unchanged lines hidden (view full) --- 445#endif 446 goto abandon; 447 } 448 } 449 cntDel++; 450 } 451 /* pull it we did it */ 452 TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); |
457 sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq); | |
458 if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 459 asoc->fragmented_delivery_inprogress = 0; 460 if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) { 461 asoc->strmin[stream_no].last_sequence_delivered++; 462 } 463 if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0) { 464 SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs); 465 } --- 30 unchanged lines hidden (view full) --- 496 while (ctl != NULL) { 497 /* Deliver more if we can. */ 498 if (nxt_todel == ctl->sinfo_ssn) { 499 ctlat = TAILQ_NEXT(ctl, next); 500 TAILQ_REMOVE(&strm->inqueue, ctl, next); 501 asoc->size_on_all_streams -= ctl->length; 502 sctp_ucount_decr(asoc->cnt_on_all_streams); 503 strm->last_sequence_delivered++; | 453 if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 454 asoc->fragmented_delivery_inprogress = 0; 455 if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) { 456 asoc->strmin[stream_no].last_sequence_delivered++; 457 } 458 if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0) { 459 SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs); 460 } --- 30 unchanged lines hidden (view full) --- 491 while (ctl != NULL) { 492 /* Deliver more if we can. */ 493 if (nxt_todel == ctl->sinfo_ssn) { 494 ctlat = TAILQ_NEXT(ctl, next); 495 TAILQ_REMOVE(&strm->inqueue, ctl, next); 496 asoc->size_on_all_streams -= ctl->length; 497 sctp_ucount_decr(asoc->cnt_on_all_streams); 498 strm->last_sequence_delivered++; |
499 sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); |
|
504 sctp_add_to_readq(stcb->sctp_ep, stcb, 505 ctl, 506 &stcb->sctp_socket->so_rcv, 1, 507 SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); | 500 sctp_add_to_readq(stcb->sctp_ep, stcb, 501 ctl, 502 &stcb->sctp_socket->so_rcv, 1, 503 SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); |
508 sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); | |
509 ctl = ctlat; 510 } else { 511 break; 512 } 513 nxt_todel = strm->last_sequence_delivered + 1; 514 } 515 } 516 break; --- 94 unchanged lines hidden (view full) --- 611 sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_IMMED_DEL); 612 } 613 /* EY it wont be queued if it could be delivered directly */ 614 queue_needed = 0; 615 asoc->size_on_all_streams -= control->length; 616 sctp_ucount_decr(asoc->cnt_on_all_streams); 617 strm->last_sequence_delivered++; 618 | 504 ctl = ctlat; 505 } else { 506 break; 507 } 508 nxt_todel = strm->last_sequence_delivered + 1; 509 } 510 } 511 break; --- 94 unchanged lines hidden (view full) --- 606 sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_IMMED_DEL); 607 } 608 /* EY it wont be queued if it could be delivered directly */ 609 queue_needed = 0; 610 asoc->size_on_all_streams -= control->length; 611 sctp_ucount_decr(asoc->cnt_on_all_streams); 612 strm->last_sequence_delivered++; 613 |
614 sctp_mark_non_revokable(asoc, control->sinfo_tsn); |
|
619 sctp_add_to_readq(stcb->sctp_ep, stcb, 620 control, 621 &stcb->sctp_socket->so_rcv, 1, 622 SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); | 615 sctp_add_to_readq(stcb->sctp_ep, stcb, 616 control, 617 &stcb->sctp_socket->so_rcv, 1, 618 SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); |
623 sctp_mark_non_revokable(asoc, control->sinfo_tsn); | |
624 control = TAILQ_FIRST(&strm->inqueue); 625 while (control != NULL) { 626 /* all delivered */ 627 nxt_todel = strm->last_sequence_delivered + 1; 628 if (nxt_todel == control->sinfo_ssn) { 629 at = TAILQ_NEXT(control, next); 630 TAILQ_REMOVE(&strm->inqueue, control, next); 631 asoc->size_on_all_streams -= control->length; --- 4 unchanged lines hidden (view full) --- 636 * since we always can hold the chunk on the 637 * d-queue. And we have a finite number that 638 * can be delivered from the strq. 639 */ 640 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 641 sctp_log_strm_del(control, NULL, 642 SCTP_STR_LOG_FROM_IMMED_DEL); 643 } | 619 control = TAILQ_FIRST(&strm->inqueue); 620 while (control != NULL) { 621 /* all delivered */ 622 nxt_todel = strm->last_sequence_delivered + 1; 623 if (nxt_todel == control->sinfo_ssn) { 624 at = TAILQ_NEXT(control, next); 625 TAILQ_REMOVE(&strm->inqueue, control, next); 626 asoc->size_on_all_streams -= control->length; --- 4 unchanged lines hidden (view full) --- 631 * since we always can hold the chunk on the 632 * d-queue. And we have a finite number that 633 * can be delivered from the strq. 634 */ 635 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 636 sctp_log_strm_del(control, NULL, 637 SCTP_STR_LOG_FROM_IMMED_DEL); 638 } |
644 /* EY will be used to calculate nr-gap */ | 639 sctp_mark_non_revokable(asoc, control->sinfo_tsn); |
645 sctp_add_to_readq(stcb->sctp_ep, stcb, 646 control, 647 &stcb->sctp_socket->so_rcv, 1, 648 SCTP_READ_LOCK_NOT_HELD, 649 SCTP_SO_NOT_LOCKED); | 640 sctp_add_to_readq(stcb->sctp_ep, stcb, 641 control, 642 &stcb->sctp_socket->so_rcv, 1, 643 SCTP_READ_LOCK_NOT_HELD, 644 SCTP_SO_NOT_LOCKED); |
650 sctp_mark_non_revokable(asoc, control->sinfo_tsn); | |
651 control = at; 652 continue; 653 } 654 break; 655 } 656 } 657 if (queue_needed) { 658 /* --- 301 unchanged lines hidden (view full) --- 960 *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); 961 } 962 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_4; 963 sctp_abort_an_association(stcb->sctp_ep, 964 stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED); 965 *abort_flag = 1; 966 } else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) != 967 SCTP_DATA_UNORDERED && | 645 control = at; 646 continue; 647 } 648 break; 649 } 650 } 651 if (queue_needed) { 652 /* --- 301 unchanged lines hidden (view full) --- 954 *ippp = ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq); 955 } 956 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_4; 957 sctp_abort_an_association(stcb->sctp_ep, 958 stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED); 959 *abort_flag = 1; 960 } else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) != 961 SCTP_DATA_UNORDERED && |
968 chk->rec.data.stream_seq != 969 asoc->ssn_of_pdapi) { | 962 chk->rec.data.stream_seq != asoc->ssn_of_pdapi) { |
970 /* Got to be the right STR Seq */ 971 SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n", 972 chk->rec.data.stream_seq, 973 asoc->ssn_of_pdapi); 974 oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 975 0, M_DONTWAIT, 1, MT_DATA); 976 if (oper) { 977 struct sctp_paramhdr *ph; --- 640 unchanged lines hidden (view full) --- 1618 /* We insert the stream in the type field */ 1619 phdr->param_type = ch->dp.stream_id; 1620 /* And set the length to 0 for the rsvd field */ 1621 phdr->param_length = 0; 1622 sctp_queue_op_err(stcb, mb); 1623 } 1624 SCTP_STAT_INCR(sctps_badsid); 1625 SCTP_TCB_LOCK_ASSERT(stcb); | 963 /* Got to be the right STR Seq */ 964 SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n", 965 chk->rec.data.stream_seq, 966 asoc->ssn_of_pdapi); 967 oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + 3 * sizeof(uint32_t)), 968 0, M_DONTWAIT, 1, MT_DATA); 969 if (oper) { 970 struct sctp_paramhdr *ph; --- 640 unchanged lines hidden (view full) --- 1611 /* We insert the stream in the type field */ 1612 phdr->param_type = ch->dp.stream_id; 1613 /* And set the length to 0 for the rsvd field */ 1614 phdr->param_length = 0; 1615 sctp_queue_op_err(stcb, mb); 1616 } 1617 SCTP_STAT_INCR(sctps_badsid); 1618 SCTP_TCB_LOCK_ASSERT(stcb); |
1626 | |
1627 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 1628 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 1629 asoc->highest_tsn_inside_nr_map = tsn; 1630 } 1631 if (tsn == (asoc->cumulative_tsn + 1)) { 1632 /* Update cum-ack */ 1633 asoc->cumulative_tsn = tsn; 1634 } --- 147 unchanged lines hidden (view full) --- 1782 asoc->strmin[strmno].last_sequence_delivered++; 1783 } 1784 SCTP_STAT_INCR(sctps_recvexpress); 1785 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 1786 sctp_log_strm_del_alt(stcb, tsn, strmseq, strmno, 1787 SCTP_STR_LOG_FROM_EXPRS_DEL); 1788 } 1789 control = NULL; | 1619 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 1620 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 1621 asoc->highest_tsn_inside_nr_map = tsn; 1622 } 1623 if (tsn == (asoc->cumulative_tsn + 1)) { 1624 /* Update cum-ack */ 1625 asoc->cumulative_tsn = tsn; 1626 } --- 147 unchanged lines hidden (view full) --- 1774 asoc->strmin[strmno].last_sequence_delivered++; 1775 } 1776 SCTP_STAT_INCR(sctps_recvexpress); 1777 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) { 1778 sctp_log_strm_del_alt(stcb, tsn, strmseq, strmno, 1779 SCTP_STR_LOG_FROM_EXPRS_DEL); 1780 } 1781 control = NULL; |
1782 |
|
1790 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 1791 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 1792 asoc->highest_tsn_inside_nr_map = tsn; 1793 } 1794 goto finish_express_del; 1795 } 1796failed_express_del: 1797 /* If we reach here this is a new chunk */ --- 50 unchanged lines hidden (view full) --- 1848 if (TAILQ_EMPTY(&asoc->reasmqueue) == 0) { 1849 /* 1850 * There could be another message 1851 * ready 1852 */ 1853 need_reasm_check = 1; 1854 } 1855 } | 1783 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 1784 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 1785 asoc->highest_tsn_inside_nr_map = tsn; 1786 } 1787 goto finish_express_del; 1788 } 1789failed_express_del: 1790 /* If we reach here this is a new chunk */ --- 50 unchanged lines hidden (view full) --- 1841 if (TAILQ_EMPTY(&asoc->reasmqueue) == 0) { 1842 /* 1843 * There could be another message 1844 * ready 1845 */ 1846 need_reasm_check = 1; 1847 } 1848 } |
1856 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); 1857 if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 1858 asoc->highest_tsn_inside_nr_map = tsn; 1859 } | |
1860 control = NULL; 1861 goto finish_express_del; 1862 } 1863 } 1864failed_pdapi_express_del: 1865 control = NULL; 1866 if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 1867 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); --- 186 unchanged lines hidden (view full) --- 2054 *abort_flag = 1; 2055 return (0); 2056 } 2057 } 2058 } 2059 /* ok, if we reach here we have passed the sanity checks */ 2060 if (chunk_flags & SCTP_DATA_UNORDERED) { 2061 /* queue directly into socket buffer */ | 1849 control = NULL; 1850 goto finish_express_del; 1851 } 1852 } 1853failed_pdapi_express_del: 1854 control = NULL; 1855 if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 1856 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap); --- 186 unchanged lines hidden (view full) --- 2043 *abort_flag = 1; 2044 return (0); 2045 } 2046 } 2047 } 2048 /* ok, if we reach here we have passed the sanity checks */ 2049 if (chunk_flags & SCTP_DATA_UNORDERED) { 2050 /* queue directly into socket buffer */ |
2051 sctp_mark_non_revokable(asoc, control->sinfo_tsn); |
|
2062 sctp_add_to_readq(stcb->sctp_ep, stcb, 2063 control, 2064 &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); | 2052 sctp_add_to_readq(stcb->sctp_ep, stcb, 2053 control, 2054 &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); |
2065 | |
2066 } else { 2067 /* 2068 * Special check for when streams are resetting. We 2069 * could be more smart about this and check the 2070 * actual stream to see if it is not being reset.. 2071 * that way we would not create a HOLB when amongst 2072 * streams being reset and those not being reset. 2073 * --- 55 unchanged lines hidden (view full) --- 2129 * the assoc is now gone and chk was put onto the 2130 * reasm queue, which has all been freed. 2131 */ 2132 *m = NULL; 2133 return (0); 2134 } 2135 } 2136finish_express_del: | 2055 } else { 2056 /* 2057 * Special check for when streams are resetting. We 2058 * could be more smart about this and check the 2059 * actual stream to see if it is not being reset.. 2060 * that way we would not create a HOLB when amongst 2061 * streams being reset and those not being reset. 2062 * --- 55 unchanged lines hidden (view full) --- 2118 * the assoc is now gone and chk was put onto the 2119 * reasm queue, which has all been freed. 2120 */ 2121 *m = NULL; 2122 return (0); 2123 } 2124 } 2125finish_express_del: |
2137 if (tsn == (asoc->cumulative_tsn + 1)) { 2138 /* Update cum-ack */ 2139 asoc->cumulative_tsn = tsn; 2140 } | |
2141 if (last_chunk) { 2142 *m = NULL; 2143 } 2144 if (ordered) { 2145 SCTP_STAT_INCR_COUNTER64(sctps_inorderchunks); 2146 } else { 2147 SCTP_STAT_INCR_COUNTER64(sctps_inunorderchunks); 2148 } --- 61 unchanged lines hidden (view full) --- 2210 if (need_reasm_check) { 2211 /* Another one waits ? */ 2212 sctp_deliver_reasm_check(stcb, asoc); 2213 } 2214 return (1); 2215} 2216 2217int8_t sctp_map_lookup_tab[256] = { | 2126 if (last_chunk) { 2127 *m = NULL; 2128 } 2129 if (ordered) { 2130 SCTP_STAT_INCR_COUNTER64(sctps_inorderchunks); 2131 } else { 2132 SCTP_STAT_INCR_COUNTER64(sctps_inunorderchunks); 2133 } --- 61 unchanged lines hidden (view full) --- 2195 if (need_reasm_check) { 2196 /* Another one waits ? */ 2197 sctp_deliver_reasm_check(stcb, asoc); 2198 } 2199 return (1); 2200} 2201 2202int8_t sctp_map_lookup_tab[256] = { |
2218 -1, 0, -1, 1, -1, 0, -1, 2, 2219 -1, 0, -1, 1, -1, 0, -1, 3, 2220 -1, 0, -1, 1, -1, 0, -1, 2, 2221 -1, 0, -1, 1, -1, 0, -1, 4, 2222 -1, 0, -1, 1, -1, 0, -1, 2, 2223 -1, 0, -1, 1, -1, 0, -1, 3, 2224 -1, 0, -1, 1, -1, 0, -1, 2, 2225 -1, 0, -1, 1, -1, 0, -1, 5, 2226 -1, 0, -1, 1, -1, 0, -1, 2, 2227 -1, 0, -1, 1, -1, 0, -1, 3, 2228 -1, 0, -1, 1, -1, 0, -1, 2, 2229 -1, 0, -1, 1, -1, 0, -1, 4, 2230 -1, 0, -1, 1, -1, 0, -1, 2, 2231 -1, 0, -1, 1, -1, 0, -1, 3, 2232 -1, 0, -1, 1, -1, 0, -1, 2, 2233 -1, 0, -1, 1, -1, 0, -1, 6, 2234 -1, 0, -1, 1, -1, 0, -1, 2, 2235 -1, 0, -1, 1, -1, 0, -1, 3, 2236 -1, 0, -1, 1, -1, 0, -1, 2, 2237 -1, 0, -1, 1, -1, 0, -1, 4, 2238 -1, 0, -1, 1, -1, 0, -1, 2, 2239 -1, 0, -1, 1, -1, 0, -1, 3, 2240 -1, 0, -1, 1, -1, 0, -1, 2, 2241 -1, 0, -1, 1, -1, 0, -1, 5, 2242 -1, 0, -1, 1, -1, 0, -1, 2, 2243 -1, 0, -1, 1, -1, 0, -1, 3, 2244 -1, 0, -1, 1, -1, 0, -1, 2, 2245 -1, 0, -1, 1, -1, 0, -1, 4, 2246 -1, 0, -1, 1, -1, 0, -1, 2, 2247 -1, 0, -1, 1, -1, 0, -1, 3, 2248 -1, 0, -1, 1, -1, 0, -1, 2, 2249 -1, 0, -1, 1, -1, 0, -1, 7, | 2203 0, 1, 0, 2, 0, 1, 0, 3, 2204 0, 1, 0, 2, 0, 1, 0, 4, 2205 0, 1, 0, 2, 0, 1, 0, 3, 2206 0, 1, 0, 2, 0, 1, 0, 5, 2207 0, 1, 0, 2, 0, 1, 0, 3, 2208 0, 1, 0, 2, 0, 1, 0, 4, 2209 0, 1, 0, 2, 0, 1, 0, 3, 2210 0, 1, 0, 2, 0, 1, 0, 6, 2211 0, 1, 0, 2, 0, 1, 0, 3, 2212 0, 1, 0, 2, 0, 1, 0, 4, 2213 0, 1, 0, 2, 0, 1, 0, 3, 2214 0, 1, 0, 2, 0, 1, 0, 5, 2215 0, 1, 0, 2, 0, 1, 0, 3, 2216 0, 1, 0, 2, 0, 1, 0, 4, 2217 0, 1, 0, 2, 0, 1, 0, 3, 2218 0, 1, 0, 2, 0, 1, 0, 7, 2219 0, 1, 0, 2, 0, 1, 0, 3, 2220 0, 1, 0, 2, 0, 1, 0, 4, 2221 0, 1, 0, 2, 0, 1, 0, 3, 2222 0, 1, 0, 2, 0, 1, 0, 5, 2223 0, 1, 0, 2, 0, 1, 0, 3, 2224 0, 1, 0, 2, 0, 1, 0, 4, 2225 0, 1, 0, 2, 0, 1, 0, 3, 2226 0, 1, 0, 2, 0, 1, 0, 6, 2227 0, 1, 0, 2, 0, 1, 0, 3, 2228 0, 1, 0, 2, 0, 1, 0, 4, 2229 0, 1, 0, 2, 0, 1, 0, 3, 2230 0, 1, 0, 2, 0, 1, 0, 5, 2231 0, 1, 0, 2, 0, 1, 0, 3, 2232 0, 1, 0, 2, 0, 1, 0, 4, 2233 0, 1, 0, 2, 0, 1, 0, 3, 2234 0, 1, 0, 2, 0, 1, 0, 8 |
2250}; 2251 2252 2253void | 2235}; 2236 2237 2238void |
2254sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort_flag) | 2239sctp_slide_mapping_arrays(struct sctp_tcb *stcb) |
2255{ 2256 /* 2257 * Now we also need to check the mapping array in a couple of ways. 2258 * 1) Did we move the cum-ack point? 2259 */ 2260 struct sctp_association *asoc; 2261 int at; | 2240{ 2241 /* 2242 * Now we also need to check the mapping array in a couple of ways. 2243 * 1) Did we move the cum-ack point? 2244 */ 2245 struct sctp_association *asoc; 2246 int at; |
2262 int last_all_ones = 0; | |
2263 int slide_from, slide_end, lgap, distance; 2264 2265 /* EY nr_mapping array variables */ 2266 /* int nr_at; */ 2267 /* int nr_last_all_ones = 0; */ 2268 /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */ 2269 uint32_t old_cumack, old_base, old_highest, highest_tsn; 2270 2271 asoc = &stcb->asoc; 2272 at = 0; 2273 2274 old_cumack = asoc->cumulative_tsn; 2275 old_base = asoc->mapping_array_base_tsn; 2276 old_highest = asoc->highest_tsn_inside_map; 2277 /* 2278 * We could probably improve this a small bit by calculating the 2279 * offset of the current cum-ack as the starting point. 2280 */ 2281 at = 0; | 2247 int slide_from, slide_end, lgap, distance; 2248 2249 /* EY nr_mapping array variables */ 2250 /* int nr_at; */ 2251 /* int nr_last_all_ones = 0; */ 2252 /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */ 2253 uint32_t old_cumack, old_base, old_highest, highest_tsn; 2254 2255 asoc = &stcb->asoc; 2256 at = 0; 2257 2258 old_cumack = asoc->cumulative_tsn; 2259 old_base = asoc->mapping_array_base_tsn; 2260 old_highest = asoc->highest_tsn_inside_map; 2261 /* 2262 * We could probably improve this a small bit by calculating the 2263 * offset of the current cum-ack as the starting point. 2264 */ 2265 at = 0; |
2282 for (slide_from = 0; slide_from < stcb->asoc.nr_mapping_array_size; slide_from++) { | 2266 for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) { |
2283 if (asoc->nr_mapping_array[slide_from] == 0xff) { 2284 at += 8; | 2267 if (asoc->nr_mapping_array[slide_from] == 0xff) { 2268 at += 8; |
2285 last_all_ones = 1; | |
2286 } else { 2287 /* there is a 0 bit */ 2288 at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]]; | 2269 } else { 2270 /* there is a 0 bit */ 2271 at += sctp_map_lookup_tab[asoc->nr_mapping_array[slide_from]]; |
2289 last_all_ones = 0; | |
2290 break; 2291 } 2292 } | 2272 break; 2273 } 2274 } |
2293 asoc->cumulative_tsn = asoc->nr_mapping_array_base_tsn + (at - last_all_ones); 2294 at++; | 2275 asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at - 1); |
2295 2296 if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) && 2297 compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN) 2298 ) { 2299#ifdef INVARIANTS 2300 panic("huh, cumack 0x%x greater than high-tsn 0x%x in map", 2301 asoc->cumulative_tsn, asoc->highest_tsn_inside_map); 2302#else --- 12 unchanged lines hidden (view full) --- 2315 MAX_TSN)) { 2316 highest_tsn = asoc->highest_tsn_inside_nr_map; 2317 } else { 2318 highest_tsn = asoc->highest_tsn_inside_map; 2319 } 2320 if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) { 2321 /* The complete array was completed by a single FR */ 2322 /* highest becomes the cum-ack */ | 2276 2277 if (compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_map, MAX_TSN) && 2278 compare_with_wrap(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN) 2279 ) { 2280#ifdef INVARIANTS 2281 panic("huh, cumack 0x%x greater than high-tsn 0x%x in map", 2282 asoc->cumulative_tsn, asoc->highest_tsn_inside_map); 2283#else --- 12 unchanged lines hidden (view full) --- 2296 MAX_TSN)) { 2297 highest_tsn = asoc->highest_tsn_inside_nr_map; 2298 } else { 2299 highest_tsn = asoc->highest_tsn_inside_map; 2300 } 2301 if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) { 2302 /* The complete array was completed by a single FR */ 2303 /* highest becomes the cum-ack */ |
2323 int clr; | 2304 int clr, i; |
2324 2325 /* clear the array */ | 2305 2306 /* clear the array */ |
2326 clr = (at >> 3) + 1; | 2307 clr = ((at + 7) >> 3); |
2327 if (clr > asoc->mapping_array_size) { 2328 clr = asoc->mapping_array_size; 2329 } 2330 memset(asoc->mapping_array, 0, clr); 2331 memset(asoc->nr_mapping_array, 0, clr); | 2308 if (clr > asoc->mapping_array_size) { 2309 clr = asoc->mapping_array_size; 2310 } 2311 memset(asoc->mapping_array, 0, clr); 2312 memset(asoc->nr_mapping_array, 0, clr); |
2332 | 2313 for (i = 0; i < asoc->mapping_array_size; i++) { 2314 if ((asoc->mapping_array[i]) || (asoc->nr_mapping_array[i])) { 2315 printf("Error Mapping array's not clean at clear\n"); 2316 sctp_print_mapping_array(asoc); 2317 } 2318 } |
2333 asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1; | 2319 asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1; |
2334 asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1; | |
2335 asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn; 2336 } else if (at >= 8) { 2337 /* we can slide the mapping array down */ 2338 /* slide_from holds where we hit the first NON 0xff byte */ 2339 2340 /* 2341 * now calculate the ceiling of the move using our highest 2342 * TSN value --- 45 unchanged lines hidden (view full) --- 2388 2389 for (ii = 0; ii < distance; ii++) { 2390 asoc->mapping_array[ii] = 2391 asoc->mapping_array[slide_from + ii]; 2392 asoc->nr_mapping_array[ii] = 2393 asoc->nr_mapping_array[slide_from + ii]; 2394 2395 } | 2320 asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn; 2321 } else if (at >= 8) { 2322 /* we can slide the mapping array down */ 2323 /* slide_from holds where we hit the first NON 0xff byte */ 2324 2325 /* 2326 * now calculate the ceiling of the move using our highest 2327 * TSN value --- 45 unchanged lines hidden (view full) --- 2373 2374 for (ii = 0; ii < distance; ii++) { 2375 asoc->mapping_array[ii] = 2376 asoc->mapping_array[slide_from + ii]; 2377 asoc->nr_mapping_array[ii] = 2378 asoc->nr_mapping_array[slide_from + ii]; 2379 2380 } |
2396 for (ii = distance; ii <= slide_end; ii++) { | 2381 for (ii = distance; ii <= asoc->mapping_array_size; ii++) { |
2397 asoc->mapping_array[ii] = 0; 2398 asoc->nr_mapping_array[ii] = 0; 2399 } 2400 asoc->mapping_array_base_tsn += (slide_from << 3); | 2382 asoc->mapping_array[ii] = 0; 2383 asoc->nr_mapping_array[ii] = 0; 2384 } 2385 asoc->mapping_array_base_tsn += (slide_from << 3); |
2401 asoc->nr_mapping_array_base_tsn += (slide_from << 3); | |
2402 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 2403 sctp_log_map(asoc->mapping_array_base_tsn, 2404 asoc->cumulative_tsn, asoc->highest_tsn_inside_map, 2405 SCTP_MAP_SLIDE_RESULT); 2406 } 2407 } 2408 } | 2386 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 2387 sctp_log_map(asoc->mapping_array_base_tsn, 2388 asoc->cumulative_tsn, asoc->highest_tsn_inside_map, 2389 SCTP_MAP_SLIDE_RESULT); 2390 } 2391 } 2392 } |
2393} 2394 2395 2396void 2397sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag) 2398{ 2399 struct sctp_association *asoc; 2400 uint32_t highest_tsn; 2401 2402 asoc = &stcb->asoc; 2403 if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, 2404 asoc->highest_tsn_inside_map, 2405 MAX_TSN)) { 2406 highest_tsn = asoc->highest_tsn_inside_nr_map; 2407 } else { 2408 highest_tsn = asoc->highest_tsn_inside_map; 2409 } 2410 |
|
2409 /* 2410 * Now we need to see if we need to queue a sack or just start the 2411 * timer (if allowed). 2412 */ | 2411 /* 2412 * Now we need to see if we need to queue a sack or just start the 2413 * timer (if allowed). 2414 */ |
2413 if (ok_to_sack) { 2414 if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 2415 /* 2416 * Ok special case, in SHUTDOWN-SENT case. here we 2417 * maker sure SACK timer is off and instead send a 2418 * SHUTDOWN and a SACK 2419 */ 2420 if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2421 sctp_timer_stop(SCTP_TIMER_TYPE_RECV, 2422 stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18); 2423 } 2424 sctp_send_shutdown(stcb, stcb->asoc.primary_destination); 2425 /* 2426 * EY if nr_sacks used then send an nr-sack , a sack 2427 * otherwise 2428 */ 2429 if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) 2430 sctp_send_nr_sack(stcb); 2431 else 2432 sctp_send_sack(stcb); 2433 } else { 2434 int is_a_gap; | 2415 if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 2416 /* 2417 * Ok special case, in SHUTDOWN-SENT case. here we maker 2418 * sure SACK timer is off and instead send a SHUTDOWN and a 2419 * SACK 2420 */ 2421 if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2422 sctp_timer_stop(SCTP_TIMER_TYPE_RECV, 2423 stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18); 2424 } 2425 sctp_send_shutdown(stcb, stcb->asoc.primary_destination); 2426 sctp_send_sack(stcb); 2427 } else { 2428 int is_a_gap; |
2435 | 2429 |
2436 /* is there a gap now ? */ 2437 is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN); | 2430 /* is there a gap now ? */ 2431 is_a_gap = compare_with_wrap(highest_tsn, stcb->asoc.cumulative_tsn, MAX_TSN); |
2438 | 2432 |
2439 /* 2440 * CMT DAC algorithm: increase number of packets 2441 * received since last ack 2442 */ 2443 stcb->asoc.cmt_dac_pkts_rcvd++; | 2433 /* 2434 * CMT DAC algorithm: increase number of packets received 2435 * since last ack 2436 */ 2437 stcb->asoc.cmt_dac_pkts_rcvd++; |
2444 | 2438 |
2445 if ((stcb->asoc.send_sack == 1) || /* We need to send a 2446 * SACK */ 2447 ((was_a_gap) && (is_a_gap == 0)) || /* was a gap, but no 2448 * longer is one */ 2449 (stcb->asoc.numduptsns) || /* we have dup's */ 2450 (is_a_gap) || /* is still a gap */ 2451 (stcb->asoc.delayed_ack == 0) || /* Delayed sack disabled */ 2452 (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */ 2453 ) { | 2439 if ((stcb->asoc.send_sack == 1) || /* We need to send a 2440 * SACK */ 2441 ((was_a_gap) && (is_a_gap == 0)) || /* was a gap, but no 2442 * longer is one */ 2443 (stcb->asoc.numduptsns) || /* we have dup's */ 2444 (is_a_gap) || /* is still a gap */ 2445 (stcb->asoc.delayed_ack == 0) || /* Delayed sack disabled */ 2446 (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) /* hit limit of pkts */ 2447 ) { |
2454 | 2448 |
2455 if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) && 2456 (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) && 2457 (stcb->asoc.send_sack == 0) && 2458 (stcb->asoc.numduptsns == 0) && 2459 (stcb->asoc.delayed_ack) && 2460 (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) { | 2449 if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) && 2450 (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) && 2451 (stcb->asoc.send_sack == 0) && 2452 (stcb->asoc.numduptsns == 0) && 2453 (stcb->asoc.delayed_ack) && 2454 (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) { |
2461 | 2455 |
2462 /* 2463 * CMT DAC algorithm: With CMT, 2464 * delay acks even in the face of 2465 * 2466 * reordering. Therefore, if acks that 2467 * do not have to be sent because of 2468 * the above reasons, will be 2469 * delayed. That is, acks that would 2470 * have been sent due to gap reports 2471 * will be delayed with DAC. Start 2472 * the delayed ack timer. 2473 */ 2474 sctp_timer_start(SCTP_TIMER_TYPE_RECV, 2475 stcb->sctp_ep, stcb, NULL); 2476 } else { 2477 /* 2478 * Ok we must build a SACK since the 2479 * timer is pending, we got our 2480 * first packet OR there are gaps or 2481 * duplicates. 2482 */ 2483 (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 2484 /* 2485 * EY if nr_sacks used then send an 2486 * nr-sack , a sack otherwise 2487 */ 2488 if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) 2489 sctp_send_nr_sack(stcb); 2490 else 2491 sctp_send_sack(stcb); 2492 } | 2456 /* 2457 * CMT DAC algorithm: With CMT, delay acks 2458 * even in the face of 2459 * 2460 * reordering. Therefore, if acks that do not 2461 * have to be sent because of the above 2462 * reasons, will be delayed. That is, acks 2463 * that would have been sent due to gap 2464 * reports will be delayed with DAC. Start 2465 * the delayed ack timer. 2466 */ 2467 sctp_timer_start(SCTP_TIMER_TYPE_RECV, 2468 stcb->sctp_ep, stcb, NULL); |
2493 } else { | 2469 } else { |
2494 if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2495 sctp_timer_start(SCTP_TIMER_TYPE_RECV, 2496 stcb->sctp_ep, stcb, NULL); 2497 } | 2470 /* 2471 * Ok we must build a SACK since the timer 2472 * is pending, we got our first packet OR 2473 * there are gaps or duplicates. 2474 */ 2475 (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 2476 sctp_send_sack(stcb); |
2498 } | 2477 } |
2478 } else { 2479 if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2480 sctp_timer_start(SCTP_TIMER_TYPE_RECV, 2481 stcb->sctp_ep, stcb, NULL); 2482 } |
|
2499 } 2500 } 2501} 2502 2503void 2504sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) 2505{ 2506 struct sctp_tmit_chunk *chk; --- 322 unchanged lines hidden (view full) --- 2829 (stcb->asoc.mapping_array[0] != 0xff)) { 2830 if ((stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) || 2831 (stcb->asoc.delayed_ack == 0) || 2832 (stcb->asoc.numduptsns) || 2833 (stcb->asoc.send_sack == 1)) { 2834 if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2835 (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 2836 } | 2483 } 2484 } 2485} 2486 2487void 2488sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) 2489{ 2490 struct sctp_tmit_chunk *chk; --- 322 unchanged lines hidden (view full) --- 2813 (stcb->asoc.mapping_array[0] != 0xff)) { 2814 if ((stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq) || 2815 (stcb->asoc.delayed_ack == 0) || 2816 (stcb->asoc.numduptsns) || 2817 (stcb->asoc.send_sack == 1)) { 2818 if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2819 (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 2820 } |
2837 /* 2838 * EY if nr_sacks used then send an nr-sack , a sack 2839 * otherwise 2840 */ 2841 if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack) 2842 sctp_send_nr_sack(stcb); 2843 else 2844 sctp_send_sack(stcb); | 2821 sctp_send_sack(stcb); |
2845 } else { 2846 if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2847 sctp_timer_start(SCTP_TIMER_TYPE_RECV, 2848 stcb->sctp_ep, stcb, NULL); 2849 } 2850 } 2851 } else { | 2822 } else { 2823 if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) { 2824 sctp_timer_start(SCTP_TIMER_TYPE_RECV, 2825 stcb->sctp_ep, stcb, NULL); 2826 } 2827 } 2828 } else { |
2852 sctp_sack_check(stcb, 1, was_a_gap, &abort_flag); | 2829 sctp_sack_check(stcb, was_a_gap, &abort_flag); |
2853 } 2854 if (abort_flag) 2855 return (2); 2856 2857 return (0); 2858} 2859 2860static int 2861sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1, uint32_t last_tsn, 2862 uint16_t frag_strt, uint16_t frag_end, int nr_sacking, 2863 int *num_frs, 2864 uint32_t * biggest_newly_acked_tsn, 2865 uint32_t * this_sack_lowest_newack, 2866 int *ecn_seg_sums) 2867{ 2868 struct sctp_tmit_chunk *tp1; 2869 unsigned int theTSN; | 2830 } 2831 if (abort_flag) 2832 return (2); 2833 2834 return (0); 2835} 2836 2837static int 2838sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1, uint32_t last_tsn, 2839 uint16_t frag_strt, uint16_t frag_end, int nr_sacking, 2840 int *num_frs, 2841 uint32_t * biggest_newly_acked_tsn, 2842 uint32_t * this_sack_lowest_newack, 2843 int *ecn_seg_sums) 2844{ 2845 struct sctp_tmit_chunk *tp1; 2846 unsigned int theTSN; |
2870 int j, wake_him = 0; | 2847 int j, wake_him = 0, circled = 0; |
2871 2872 /* Recover the tp1 we last saw */ 2873 tp1 = *p_tp1; 2874 if (tp1 == NULL) { 2875 tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 2876 } 2877 for (j = frag_strt; j <= frag_end; j++) { 2878 theTSN = j + last_tsn; --- 161 unchanged lines hidden (view full) --- 3040 3041 if (tp1->rec.data.chunk_was_revoked) { 3042 /* deflate the cwnd */ 3043 tp1->whoTo->cwnd -= tp1->book_size; 3044 tp1->rec.data.chunk_was_revoked = 0; 3045 } 3046 /* NR Sack code here */ 3047 if (nr_sacking) { | 2848 2849 /* Recover the tp1 we last saw */ 2850 tp1 = *p_tp1; 2851 if (tp1 == NULL) { 2852 tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 2853 } 2854 for (j = frag_strt; j <= frag_end; j++) { 2855 theTSN = j + last_tsn; --- 161 unchanged lines hidden (view full) --- 3017 3018 if (tp1->rec.data.chunk_was_revoked) { 3019 /* deflate the cwnd */ 3020 tp1->whoTo->cwnd -= tp1->book_size; 3021 tp1->rec.data.chunk_was_revoked = 0; 3022 } 3023 /* NR Sack code here */ 3024 if (nr_sacking) { |
3048 if (tp1->sent != SCTP_FORWARD_TSN_SKIP) 3049 tp1->sent = SCTP_DATAGRAM_NR_MARKED; 3050 /* 3051 * TAILQ_REMOVE(&asoc->sent_q 3052 * ueue, tp1, sctp_next); 3053 */ | |
3054 if (tp1->data) { 3055 /* 3056 * sa_ignore 3057 * NO_NULL_CHK 3058 */ 3059 sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 3060 sctp_m_freem(tp1->data); | 3025 if (tp1->data) { 3026 /* 3027 * sa_ignore 3028 * NO_NULL_CHK 3029 */ 3030 sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 3031 sctp_m_freem(tp1->data); |
3032 tp1->data = NULL; |
|
3061 } | 3033 } |
3062 tp1->data = NULL; 3063 /* asoc->sent_queue_cnt--; */ 3064 /* 3065 * sctp_free_a_chunk(stcb, 3066 * tp1); 3067 */ | |
3068 wake_him++; 3069 } 3070 } 3071 break; 3072 } /* if (tp1->TSN_seq == theTSN) */ 3073 if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN, 3074 MAX_TSN)) 3075 break; 3076 3077 tp1 = TAILQ_NEXT(tp1, sctp_next); | 3034 wake_him++; 3035 } 3036 } 3037 break; 3038 } /* if (tp1->TSN_seq == theTSN) */ 3039 if (compare_with_wrap(tp1->rec.data.TSN_seq, theTSN, 3040 MAX_TSN)) 3041 break; 3042 3043 tp1 = TAILQ_NEXT(tp1, sctp_next); |
3044 if ((tp1 == NULL) && (circled == 0)) { 3045 circled++; 3046 tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 3047 } |
|
3078 } /* end while (tp1) */ | 3048 } /* end while (tp1) */ |
3079 /* In case the fragments were not in order we must reset */ | |
3080 if (tp1 == NULL) { | 3049 if (tp1 == NULL) { |
3050 circled = 0; |
|
3081 tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 3082 } | 3051 tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue); 3052 } |
3053 /* In case the fragments were not in order we must reset */ |
|
3083 } /* end for (j = fragStart */ 3084 *p_tp1 = tp1; 3085 return (wake_him); /* Return value only used for nr-sack */ 3086} 3087 3088 3089static int 3090sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc, --- 62 unchanged lines hidden (view full) --- 3153 } 3154 last_frag_high = frag_end + last_tsn; 3155 } 3156 if (i < num_seg) { 3157 non_revocable = 0; 3158 } else { 3159 non_revocable = 1; 3160 } | 3054 } /* end for (j = fragStart */ 3055 *p_tp1 = tp1; 3056 return (wake_him); /* Return value only used for nr-sack */ 3057} 3058 3059 3060static int 3061sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc, --- 62 unchanged lines hidden (view full) --- 3124 } 3125 last_frag_high = frag_end + last_tsn; 3126 } 3127 if (i < num_seg) { 3128 non_revocable = 0; 3129 } else { 3130 non_revocable = 1; 3131 } |
3132 if (i == num_seg) { 3133 tp1 = NULL; 3134 } |
|
3161 if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, 3162 non_revocable, &num_frs, biggest_newly_acked_tsn, 3163 this_sack_lowest_newack, ecn_seg_sums)) { 3164 chunk_freed = 1; 3165 } 3166 } 3167 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 3168 if (num_frs) --- 787 unchanged lines hidden (view full) --- 3956 compare_with_wrap(cumack, send_s, MAX_TSN)) { 3957#ifndef INVARIANTS 3958 struct mbuf *oper; 3959 3960#endif 3961#ifdef INVARIANTS 3962 panic("Impossible sack 1"); 3963#else | 3135 if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end, 3136 non_revocable, &num_frs, biggest_newly_acked_tsn, 3137 this_sack_lowest_newack, ecn_seg_sums)) { 3138 chunk_freed = 1; 3139 } 3140 } 3141 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) { 3142 if (num_frs) --- 787 unchanged lines hidden (view full) --- 3930 compare_with_wrap(cumack, send_s, MAX_TSN)) { 3931#ifndef INVARIANTS 3932 struct mbuf *oper; 3933 3934#endif 3935#ifdef INVARIANTS 3936 panic("Impossible sack 1"); 3937#else |
3938 |
|
3964 *abort_now = 1; 3965 /* XXX */ 3966 oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), 3967 0, M_DONTWAIT, 1, MT_DATA); 3968 if (oper) { 3969 struct sctp_paramhdr *ph; 3970 uint32_t *ippp; 3971 --- 462 unchanged lines hidden (view full) --- 4434 sctp_misc_ints(SCTP_SACK_RWND_UPDATE, 4435 rwnd, 4436 stcb->asoc.peers_rwnd, 4437 stcb->asoc.total_flight, 4438 stcb->asoc.total_output_queue_size); 4439 } 4440} 4441 | 3939 *abort_now = 1; 3940 /* XXX */ 3941 oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), 3942 0, M_DONTWAIT, 1, MT_DATA); 3943 if (oper) { 3944 struct sctp_paramhdr *ph; 3945 uint32_t *ippp; 3946 --- 462 unchanged lines hidden (view full) --- 4409 sctp_misc_ints(SCTP_SACK_RWND_UPDATE, 4410 rwnd, 4411 stcb->asoc.peers_rwnd, 4412 stcb->asoc.total_flight, 4413 stcb->asoc.total_output_queue_size); 4414 } 4415} 4416 |
4442/* EY- nr_sack */ 4443/* Identifies the non-renegable tsns that are revoked*/ 4444static void 4445sctp_check_for_nr_revoked(struct sctp_tcb *stcb, 4446 struct sctp_association *asoc, uint32_t cumack, 4447 uint32_t biggest_tsn_acked) 4448{ 4449 struct sctp_tmit_chunk *tp1; 4450 4451 for (tp1 = TAILQ_FIRST(&asoc->sent_queue); tp1; tp1 = TAILQ_NEXT(tp1, sctp_next)) { 4452 if (compare_with_wrap(tp1->rec.data.TSN_seq, cumack, 4453 MAX_TSN)) { 4454 /* 4455 * ok this guy is either ACK or MARKED. If it is 4456 * ACKED it has been previously acked but not this 4457 * time i.e. revoked. If it is MARKED it was ACK'ed 4458 * again. 4459 */ 4460 if (compare_with_wrap(tp1->rec.data.TSN_seq, biggest_tsn_acked, 4461 MAX_TSN)) 4462 break; 4463 4464 4465 if (tp1->sent == SCTP_DATAGRAM_NR_ACKED) { 4466 /* 4467 * EY! a non-renegable TSN is revoked, need 4468 * to abort the association 4469 */ 4470 /* 4471 * EY TODO: put in the code to abort the 4472 * assoc. 4473 */ 4474 return; 4475 } else if (tp1->sent == SCTP_DATAGRAM_NR_MARKED) { 4476 /* it has been re-acked in this SACK */ 4477 tp1->sent = SCTP_DATAGRAM_NR_ACKED; 4478 } 4479 } 4480 if (tp1->sent == SCTP_DATAGRAM_UNSENT) 4481 break; 4482 } 4483 return; 4484} 4485 | |
4486void 4487sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, 4488 struct sctp_tcb *stcb, struct sctp_nets *net_from, 4489 uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup, 4490 int *abort_now, uint8_t flags, 4491 uint32_t cum_ack, uint32_t rwnd) 4492{ 4493 struct sctp_association *asoc; --- 89 unchanged lines hidden (view full) --- 4583 } 4584 if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) { 4585 /* reality check */ 4586 if (!TAILQ_EMPTY(&asoc->sent_queue)) { 4587 tp1 = TAILQ_LAST(&asoc->sent_queue, 4588 sctpchunk_listhead); 4589 send_s = tp1->rec.data.TSN_seq + 1; 4590 } else { | 4417void 4418sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup, 4419 struct sctp_tcb *stcb, struct sctp_nets *net_from, 4420 uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup, 4421 int *abort_now, uint8_t flags, 4422 uint32_t cum_ack, uint32_t rwnd) 4423{ 4424 struct sctp_association *asoc; --- 89 unchanged lines hidden (view full) --- 4514 } 4515 if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) { 4516 /* reality check */ 4517 if (!TAILQ_EMPTY(&asoc->sent_queue)) { 4518 tp1 = TAILQ_LAST(&asoc->sent_queue, 4519 sctpchunk_listhead); 4520 send_s = tp1->rec.data.TSN_seq + 1; 4521 } else { |
4522 tp1 = NULL; |
|
4591 send_s = asoc->sending_seq; 4592 } 4593 if (cum_ack == send_s || 4594 compare_with_wrap(cum_ack, send_s, MAX_TSN)) { | 4523 send_s = asoc->sending_seq; 4524 } 4525 if (cum_ack == send_s || 4526 compare_with_wrap(cum_ack, send_s, MAX_TSN)) { |
4595#ifndef INVARIANTS | |
4596 struct mbuf *oper; 4597 | 4527 struct mbuf *oper; 4528 |
4598#endif 4599#ifdef INVARIANTS 4600 hopeless_peer: 4601 panic("Impossible sack 1"); 4602#else | |
4603 /* 4604 * no way, we have not even sent this TSN out yet. 4605 * Peer is hopelessly messed up with us. 4606 */ | 4529 /* 4530 * no way, we have not even sent this TSN out yet. 4531 * Peer is hopelessly messed up with us. 4532 */ |
4533 printf("NEW cum_ack:%x send_s:%x is smaller or equal\n", 4534 cum_ack, send_s); 4535 if (tp1) { 4536 printf("Got send_s from tsn:%x + 1 of tp1:%p\n", 4537 tp1->rec.data.TSN_seq, tp1); 4538 } |
|
4607 hopeless_peer: 4608 *abort_now = 1; 4609 /* XXX */ 4610 oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), 4611 0, M_DONTWAIT, 1, MT_DATA); 4612 if (oper) { 4613 struct sctp_paramhdr *ph; 4614 uint32_t *ippp; --- 4 unchanged lines hidden (view full) --- 4619 ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); 4620 ph->param_length = htons(SCTP_BUF_LEN(oper)); 4621 ippp = (uint32_t *) (ph + 1); 4622 *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); 4623 } 4624 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; 4625 sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED); 4626 return; | 4539 hopeless_peer: 4540 *abort_now = 1; 4541 /* XXX */ 4542 oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)), 4543 0, M_DONTWAIT, 1, MT_DATA); 4544 if (oper) { 4545 struct sctp_paramhdr *ph; 4546 uint32_t *ippp; --- 4 unchanged lines hidden (view full) --- 4551 ph->param_type = htons(SCTP_CAUSE_PROTOCOL_VIOLATION); 4552 ph->param_length = htons(SCTP_BUF_LEN(oper)); 4553 ippp = (uint32_t *) (ph + 1); 4554 *ippp = htonl(SCTP_FROM_SCTP_INDATA + SCTP_LOC_25); 4555 } 4556 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25; 4557 sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED); 4558 return; |
4627#endif | |
4628 } 4629 } 4630 /**********************/ 4631 /* 1) check the range */ 4632 /**********************/ 4633 if (compare_with_wrap(asoc->last_acked_seq, last_tsn, MAX_TSN)) { 4634 /* acking something behind */ 4635 return; --- 203 unchanged lines hidden (view full) --- 4839 * strict adherence is wanted. 4840 */ 4841 if ((biggest_tsn_acked == send_s) || 4842 (compare_with_wrap(biggest_tsn_acked, send_s, MAX_TSN))) { 4843 /* 4844 * peer is either confused or we are under 4845 * attack. We must abort. 4846 */ | 4559 } 4560 } 4561 /**********************/ 4562 /* 1) check the range */ 4563 /**********************/ 4564 if (compare_with_wrap(asoc->last_acked_seq, last_tsn, MAX_TSN)) { 4565 /* acking something behind */ 4566 return; --- 203 unchanged lines hidden (view full) --- 4770 * strict adherence is wanted. 4771 */ 4772 if ((biggest_tsn_acked == send_s) || 4773 (compare_with_wrap(biggest_tsn_acked, send_s, MAX_TSN))) { 4774 /* 4775 * peer is either confused or we are under 4776 * attack. We must abort. 4777 */ |
4778 printf("Hopeless peer! biggest_tsn_acked:%x largest seq:%x\n", 4779 biggest_tsn_acked, 4780 send_s); 4781 |
|
4847 goto hopeless_peer; 4848 } 4849 } 4850 } 4851 /*******************************************/ 4852 /* cancel ALL T3-send timer if accum moved */ 4853 /*******************************************/ 4854 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) { --- 131 unchanged lines hidden (view full) --- 4986 /* Peer revoked all dg's marked or acked */ 4987 TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 4988 /* 4989 * EY- maybe check only if it is nr_acked 4990 * nr_marked may not be possible 4991 */ 4992 if ((tp1->sent == SCTP_DATAGRAM_NR_ACKED) || 4993 (tp1->sent == SCTP_DATAGRAM_NR_MARKED)) { | 4782 goto hopeless_peer; 4783 } 4784 } 4785 } 4786 /*******************************************/ 4787 /* cancel ALL T3-send timer if accum moved */ 4788 /*******************************************/ 4789 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) { --- 131 unchanged lines hidden (view full) --- 4921 /* Peer revoked all dg's marked or acked */ 4922 TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) { 4923 /* 4924 * EY- maybe check only if it is nr_acked 4925 * nr_marked may not be possible 4926 */ 4927 if ((tp1->sent == SCTP_DATAGRAM_NR_ACKED) || 4928 (tp1->sent == SCTP_DATAGRAM_NR_MARKED)) { |
4994 /* 4995 * EY! - TODO: Something previously 4996 * nr_gapped is reneged, abort the 4997 * association 4998 */ 4999 return; | 4929 continue; |
5000 } | 4930 } |
5001 if ((tp1->sent > SCTP_DATAGRAM_RESEND) && 5002 (tp1->sent < SCTP_FORWARD_TSN_SKIP)) { | 4931 if (tp1->sent == SCTP_DATAGRAM_ACKED) { |
5003 tp1->sent = SCTP_DATAGRAM_SENT; 5004 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 5005 sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE, 5006 tp1->whoTo->flight_size, 5007 tp1->book_size, 5008 (uintptr_t) tp1->whoTo, 5009 tp1->rec.data.TSN_seq); 5010 } --- 12 unchanged lines hidden (view full) --- 5023 } 5024 } 5025 if (cnt_revoked) { 5026 reneged_all = 1; 5027 } 5028 } 5029 asoc->saw_sack_with_frags = 0; 5030 } | 4932 tp1->sent = SCTP_DATAGRAM_SENT; 4933 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 4934 sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE, 4935 tp1->whoTo->flight_size, 4936 tp1->book_size, 4937 (uintptr_t) tp1->whoTo, 4938 tp1->rec.data.TSN_seq); 4939 } --- 12 unchanged lines hidden (view full) --- 4952 } 4953 } 4954 if (cnt_revoked) { 4955 reneged_all = 1; 4956 } 4957 } 4958 asoc->saw_sack_with_frags = 0; 4959 } |
5031 if (num_seg) | 4960 if (num_seg || num_nr_seg) |
5032 asoc->saw_sack_with_frags = 1; 5033 else 5034 asoc->saw_sack_with_frags = 0; 5035 | 4961 asoc->saw_sack_with_frags = 1; 4962 else 4963 asoc->saw_sack_with_frags = 0; 4964 |
5036 /* EY! - not sure about if there should be an IF */ 5037 if (num_nr_seg > 0) 5038 sctp_check_for_nr_revoked(stcb, asoc, cum_ack, biggest_tsn_acked); 5039 | |
5040 /* JRS - Use the congestion control given in the CC module */ 5041 asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery); 5042 5043 if (TAILQ_EMPTY(&asoc->sent_queue)) { 5044 /* nothing left in-flight */ 5045 TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 5046 /* stop all timers */ 5047 if (SCTP_BASE_SYSCTL(sctp_early_fr)) { --- 404 unchanged lines hidden (view full) --- 5452 (tt == ctl->sinfo_ssn)) { 5453 /* this is deliverable now */ 5454 TAILQ_REMOVE(&strmin->inqueue, ctl, next); 5455 /* subtract pending on streams */ 5456 asoc->size_on_all_streams -= ctl->length; 5457 sctp_ucount_decr(asoc->cnt_on_all_streams); 5458 /* deliver it to at least the delivery-q */ 5459 if (stcb->sctp_socket) { | 4965 /* JRS - Use the congestion control given in the CC module */ 4966 asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery); 4967 4968 if (TAILQ_EMPTY(&asoc->sent_queue)) { 4969 /* nothing left in-flight */ 4970 TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 4971 /* stop all timers */ 4972 if (SCTP_BASE_SYSCTL(sctp_early_fr)) { --- 404 unchanged lines hidden (view full) --- 5377 (tt == ctl->sinfo_ssn)) { 5378 /* this is deliverable now */ 5379 TAILQ_REMOVE(&strmin->inqueue, ctl, next); 5380 /* subtract pending on streams */ 5381 asoc->size_on_all_streams -= ctl->length; 5382 sctp_ucount_decr(asoc->cnt_on_all_streams); 5383 /* deliver it to at least the delivery-q */ 5384 if (stcb->sctp_socket) { |
5460 /* EY need the tsn info for calculating nr */ | 5385 sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); |
5461 sctp_add_to_readq(stcb->sctp_ep, stcb, 5462 ctl, 5463 &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); | 5386 sctp_add_to_readq(stcb->sctp_ep, stcb, 5387 ctl, 5388 &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); |
5464 sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); | |
5465 } 5466 } else { 5467 /* no more delivery now. */ 5468 break; 5469 } 5470 ctl = nctl; 5471 } 5472 /* --- 8 unchanged lines hidden (view full) --- 5481 /* this is deliverable now */ 5482 TAILQ_REMOVE(&strmin->inqueue, ctl, next); 5483 /* subtract pending on streams */ 5484 asoc->size_on_all_streams -= ctl->length; 5485 sctp_ucount_decr(asoc->cnt_on_all_streams); 5486 /* deliver it to at least the delivery-q */ 5487 strmin->last_sequence_delivered = ctl->sinfo_ssn; 5488 if (stcb->sctp_socket) { | 5389 } 5390 } else { 5391 /* no more delivery now. */ 5392 break; 5393 } 5394 ctl = nctl; 5395 } 5396 /* --- 8 unchanged lines hidden (view full) --- 5405 /* this is deliverable now */ 5406 TAILQ_REMOVE(&strmin->inqueue, ctl, next); 5407 /* subtract pending on streams */ 5408 asoc->size_on_all_streams -= ctl->length; 5409 sctp_ucount_decr(asoc->cnt_on_all_streams); 5410 /* deliver it to at least the delivery-q */ 5411 strmin->last_sequence_delivered = ctl->sinfo_ssn; 5412 if (stcb->sctp_socket) { |
5413 sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); |
|
5489 sctp_add_to_readq(stcb->sctp_ep, stcb, 5490 ctl, 5491 &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); | 5414 sctp_add_to_readq(stcb->sctp_ep, stcb, 5415 ctl, 5416 &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED); |
5492 sctp_mark_non_revokable(asoc, ctl->sinfo_tsn); | |
5493 5494 } 5495 tt = strmin->last_sequence_delivered + 1; 5496 } else { 5497 break; 5498 } 5499 ctl = nctl; 5500 } --- 87 unchanged lines hidden (view full) --- 5588 chk = at; 5589 } 5590 } 5591} 5592 5593 5594void 5595sctp_handle_forward_tsn(struct sctp_tcb *stcb, | 5417 5418 } 5419 tt = strmin->last_sequence_delivered + 1; 5420 } else { 5421 break; 5422 } 5423 ctl = nctl; 5424 } --- 87 unchanged lines hidden (view full) --- 5512 chk = at; 5513 } 5514 } 5515} 5516 5517 5518void 5519sctp_handle_forward_tsn(struct sctp_tcb *stcb, |
5596 struct sctp_forward_tsn_chunk *fwd, int *abort_flag, struct mbuf *m, int offset) | 5520 struct sctp_forward_tsn_chunk *fwd, 5521 int *abort_flag, struct mbuf *m, int offset) |
5597{ 5598 /* 5599 * ISSUES that MUST be fixed for ECN! When we are the sender of the 5600 * forward TSN, when the SACK comes back that acknowledges the 5601 * FWD-TSN we must reset the NONCE sum to match correctly. This will 5602 * get quite tricky since we may have sent more data interveneing 5603 * and must carefully account for what the SACK says on the nonce 5604 * and any gaps that are reported. This work will NOT be done here, --- 9 unchanged lines hidden (view full) --- 5614 * Assume we get FwdTSN(x): 5615 * 5616 * 1) update local cumTSN to x 2) try to further advance cumTSN to x + 5617 * others we have 3) examine and update re-ordering queue on 5618 * pr-in-streams 4) clean up re-assembly queue 5) Send a sack to 5619 * report where we are. 5620 */ 5621 struct sctp_association *asoc; | 5522{ 5523 /* 5524 * ISSUES that MUST be fixed for ECN! When we are the sender of the 5525 * forward TSN, when the SACK comes back that acknowledges the 5526 * FWD-TSN we must reset the NONCE sum to match correctly. This will 5527 * get quite tricky since we may have sent more data interveneing 5528 * and must carefully account for what the SACK says on the nonce 5529 * and any gaps that are reported. This work will NOT be done here, --- 9 unchanged lines hidden (view full) --- 5539 * Assume we get FwdTSN(x): 5540 * 5541 * 1) update local cumTSN to x 2) try to further advance cumTSN to x + 5542 * others we have 3) examine and update re-ordering queue on 5543 * pr-in-streams 4) clean up re-assembly queue 5) Send a sack to 5544 * report where we are. 5545 */ 5546 struct sctp_association *asoc; |
5622 uint32_t new_cum_tsn, gap; 5623 unsigned int i, fwd_sz, cumack_set_flag, m_size; | 5547 uint32_t new_cum_tsn, tsn, gap; 5548 unsigned int i, fwd_sz, cumack_set_flag, m_size, fnd = 0; |
5624 uint32_t str_seq; 5625 struct sctp_stream_in *strm; 5626 struct sctp_tmit_chunk *chk, *at; 5627 struct sctp_queued_to_read *ctl, *sv; 5628 5629 cumack_set_flag = 0; 5630 asoc = &stcb->asoc; 5631 if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) { --- 20 unchanged lines hidden (view full) --- 5652 if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, 5653 MAX_TSN)) { 5654 asoc->highest_tsn_inside_nr_map = new_cum_tsn; 5655 } 5656 /* 5657 * now we know the new TSN is more advanced, let's find the actual 5658 * gap 5659 */ | 5549 uint32_t str_seq; 5550 struct sctp_stream_in *strm; 5551 struct sctp_tmit_chunk *chk, *at; 5552 struct sctp_queued_to_read *ctl, *sv; 5553 5554 cumack_set_flag = 0; 5555 asoc = &stcb->asoc; 5556 if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) { --- 20 unchanged lines hidden (view full) --- 5577 if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, 5578 MAX_TSN)) { 5579 asoc->highest_tsn_inside_nr_map = new_cum_tsn; 5580 } 5581 /* 5582 * now we know the new TSN is more advanced, let's find the actual 5583 * gap 5584 */ |
5660 SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->nr_mapping_array_base_tsn); | 5585 SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn); |
5661 asoc->cumulative_tsn = new_cum_tsn; 5662 if (gap >= m_size) { 5663 if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) { 5664 struct mbuf *oper; 5665 5666 /* 5667 * out of range (of single byte chunks in the rwnd I 5668 * give out). This must be an attacker. --- 23 unchanged lines hidden (view full) --- 5692 return; 5693 } 5694 SCTP_STAT_INCR(sctps_fwdtsn_map_over); 5695 5696 memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 5697 asoc->mapping_array_base_tsn = new_cum_tsn + 1; 5698 asoc->highest_tsn_inside_map = new_cum_tsn; 5699 | 5586 asoc->cumulative_tsn = new_cum_tsn; 5587 if (gap >= m_size) { 5588 if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) { 5589 struct mbuf *oper; 5590 5591 /* 5592 * out of range (of single byte chunks in the rwnd I 5593 * give out). This must be an attacker. --- 23 unchanged lines hidden (view full) --- 5617 return; 5618 } 5619 SCTP_STAT_INCR(sctps_fwdtsn_map_over); 5620 5621 memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 5622 asoc->mapping_array_base_tsn = new_cum_tsn + 1; 5623 asoc->highest_tsn_inside_map = new_cum_tsn; 5624 |
5700 memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.nr_mapping_array_size); 5701 asoc->nr_mapping_array_base_tsn = new_cum_tsn + 1; | 5625 memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); |
5702 asoc->highest_tsn_inside_nr_map = new_cum_tsn; 5703 5704 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 5705 sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 5706 } 5707 asoc->last_echo_tsn = asoc->highest_tsn_inside_map; 5708 } else { 5709 SCTP_TCB_LOCK_ASSERT(stcb); 5710 for (i = 0; i <= gap; i++) { 5711 SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, i); 5712 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); | 5626 asoc->highest_tsn_inside_nr_map = new_cum_tsn; 5627 5628 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 5629 sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 5630 } 5631 asoc->last_echo_tsn = asoc->highest_tsn_inside_map; 5632 } else { 5633 SCTP_TCB_LOCK_ASSERT(stcb); 5634 for (i = 0; i <= gap; i++) { 5635 SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, i); 5636 SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i); |
5637 /* FIX ME add something to set up highest TSN in map */ |
|
5713 } | 5638 } |
5639 if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) { 5640 asoc->highest_tsn_inside_nr_map = new_cum_tsn; 5641 } 5642 if (compare_with_wrap(new_cum_tsn, asoc->highest_tsn_inside_map, MAX_TSN) || 5643 new_cum_tsn == asoc->highest_tsn_inside_map) { 5644 /* We must back down to see what the new highest is */ 5645 for (tsn = new_cum_tsn; (compare_with_wrap(tsn, asoc->mapping_array_base_tsn, MAX_TSN) || 5646 (tsn == asoc->mapping_array_base_tsn)); tsn--) { 5647 SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn); 5648 if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 5649 asoc->highest_tsn_inside_map = tsn; 5650 fnd = 1; 5651 break; 5652 } 5653 } 5654 if (!fnd) { 5655 asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1; 5656 } 5657 } |
|
5714 /* 5715 * Now after marking all, slide thing forward but no sack 5716 * please. 5717 */ | 5658 /* 5659 * Now after marking all, slide thing forward but no sack 5660 * please. 5661 */ |
5718 sctp_sack_check(stcb, 0, 0, abort_flag); 5719 if (*abort_flag) 5720 return; | 5662 sctp_slide_mapping_arrays(stcb); |
5721 } 5722 /*************************************************************/ 5723 /* 2. Clear up re-assembly queue */ 5724 /*************************************************************/ 5725 /* 5726 * First service it if pd-api is up, just in case we can progress it 5727 * forward 5728 */ --- 168 unchanged lines hidden --- | 5663 } 5664 /*************************************************************/ 5665 /* 2. Clear up re-assembly queue */ 5666 /*************************************************************/ 5667 /* 5668 * First service it if pd-api is up, just in case we can progress it 5669 * forward 5670 */ --- 168 unchanged lines hidden --- |