Deleted Added
full compact
sctp_output.c (205627) sctp_output.c (206137)
1/*-
2 * Copyright (c) 2001-2008, 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_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */
32
33#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001-2008, 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_output.c,v 1.46 2005/03/06 16:04:17 itojun Exp $ */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 205627 2010-03-24 19:45:36Z rrs $");
34__FBSDID("$FreeBSD: head/sys/netinet/sctp_output.c 206137 2010-04-03 15:40:14Z tuexen $");
35
36#include <netinet/sctp_os.h>
37#include <sys/proc.h>
38#include <netinet/sctp_var.h>
39#include <netinet/sctp_sysctl.h>
40#include <netinet/sctp_header.h>
41#include <netinet/sctp_pcb.h>
42#include <netinet/sctputil.h>

--- 8955 unchanged lines hidden (view full) ---

8998 sctp_auditing(20, inp, stcb, NULL);
8999#endif
9000 data_auth_reqd = sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks);
9001 TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
9002 if (chk->sent != SCTP_DATAGRAM_RESEND) {
9003 /* No, not sent to this net or not ready for rtx */
9004 continue;
9005 }
35
36#include <netinet/sctp_os.h>
37#include <sys/proc.h>
38#include <netinet/sctp_var.h>
39#include <netinet/sctp_sysctl.h>
40#include <netinet/sctp_header.h>
41#include <netinet/sctp_pcb.h>
42#include <netinet/sctputil.h>

--- 8955 unchanged lines hidden (view full) ---

8998 sctp_auditing(20, inp, stcb, NULL);
8999#endif
9000 data_auth_reqd = sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks);
9001 TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
9002 if (chk->sent != SCTP_DATAGRAM_RESEND) {
9003 /* No, not sent to this net or not ready for rtx */
9004 continue;
9005 }
9006 if (chk->data == NULL) {
9007 printf("TSN:%x chk->snd_count:%d chk->sent:%d can't retran - no data\n",
9008 chk->rec.data.TSN_seq, chk->snd_count, chk->sent);
9009 continue;
9010 }
9006 if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) &&
9007 (chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) {
9008 /* Gak, we have exceeded max unlucky retran, abort! */
9009 SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n",
9010 chk->snd_count,
9011 SCTP_BASE_SYSCTL(sctp_max_retran_chunk));
9012 atomic_add_int(&stcb->asoc.refcnt, 1);
9013 sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL, so_locked);

--- 407 unchanged lines hidden (view full) ---

9421 /* Nothing to do unless there is something to be sent left */
9422 return;
9423 }
9424 /*
9425 * Do we have something to send, data or control AND a sack timer
9426 * running, if so piggy-back the sack.
9427 */
9428 if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
9011 if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) &&
9012 (chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) {
9013 /* Gak, we have exceeded max unlucky retran, abort! */
9014 SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n",
9015 chk->snd_count,
9016 SCTP_BASE_SYSCTL(sctp_max_retran_chunk));
9017 atomic_add_int(&stcb->asoc.refcnt, 1);
9018 sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL, so_locked);

--- 407 unchanged lines hidden (view full) ---

9426 /* Nothing to do unless there is something to be sent left */
9427 return;
9428 }
9429 /*
9430 * Do we have something to send, data or control AND a sack timer
9431 * running, if so piggy-back the sack.
9432 */
9433 if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
9429 /*
9430 * EY if nr_sacks used then send an nr-sack , a sack
9431 * otherwise
9432 */
9433 if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack)
9434 sctp_send_nr_sack(stcb);
9435 else
9436 sctp_send_sack(stcb);
9434 sctp_send_sack(stcb);
9437 (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
9438 }
9439 while (asoc->sent_queue_retran_cnt) {
9440 /*-
9441 * Ok, it is retransmission time only, we send out only ONE
9442 * packet with a single call off to the retran code.
9443 */
9444 if (from_where == SCTP_OUTPUT_FROM_COOKIE_ACK) {

--- 406 unchanged lines hidden (view full) ---

9851 return;
9852
9853}
9854
9855void
9856sctp_send_sack(struct sctp_tcb *stcb)
9857{
9858 /*-
9435 (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
9436 }
9437 while (asoc->sent_queue_retran_cnt) {
9438 /*-
9439 * Ok, it is retransmission time only, we send out only ONE
9440 * packet with a single call off to the retran code.
9441 */
9442 if (from_where == SCTP_OUTPUT_FROM_COOKIE_ACK) {

--- 406 unchanged lines hidden (view full) ---

9849 return;
9850
9851}
9852
9853void
9854sctp_send_sack(struct sctp_tcb *stcb)
9855{
9856 /*-
9859 * Queue up a SACK in the control queue. We must first check to see
9860 * if a SACK is somehow on the control queue. If so, we will take
9861 * and and remove the old one.
9857 * Queue up a SACK or NR-SACK in the control queue.
9858 * We must first check to see if a SACK or NR-SACK is
9859 * somehow on the control queue.
9860 * If so, we will take and and remove the old one.
9862 */
9863 struct sctp_association *asoc;
9864 struct sctp_tmit_chunk *chk, *a_chk;
9865 struct sctp_sack_chunk *sack;
9861 */
9862 struct sctp_association *asoc;
9863 struct sctp_tmit_chunk *chk, *a_chk;
9864 struct sctp_sack_chunk *sack;
9865 struct sctp_nr_sack_chunk *nr_sack;
9866 struct sctp_gap_ack_block *gap_descriptor;
9867 struct sack_track *selector;
9868 int mergeable = 0;
9869 int offset;
9870 caddr_t limit;
9871 uint32_t *dup;
9872 int limit_reached = 0;
9866 struct sctp_gap_ack_block *gap_descriptor;
9867 struct sack_track *selector;
9868 int mergeable = 0;
9869 int offset;
9870 caddr_t limit;
9871 uint32_t *dup;
9872 int limit_reached = 0;
9873 unsigned int i, jstart, siz, j;
9874 unsigned int num_gap_blocks = 0, space;
9873 unsigned int i, sel_start, siz, j, starting_index;
9874 unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space;
9875 int num_dups = 0;
9876 int space_req;
9877 uint32_t highest_tsn;
9875 int num_dups = 0;
9876 int space_req;
9877 uint32_t highest_tsn;
9878 uint8_t flags;
9879 uint8_t type;
9878
9880
9881 if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
9882 stcb->asoc.peer_supports_nr_sack) {
9883 type = SCTP_NR_SELECTIVE_ACK;
9884 } else {
9885 type = SCTP_SELECTIVE_ACK;
9886 }
9879 a_chk = NULL;
9880 asoc = &stcb->asoc;
9881 SCTP_TCB_LOCK_ASSERT(stcb);
9882 if (asoc->last_data_chunk_from == NULL) {
9883 /* Hmm we never received anything */
9884 return;
9885 }
9887 a_chk = NULL;
9888 asoc = &stcb->asoc;
9889 SCTP_TCB_LOCK_ASSERT(stcb);
9890 if (asoc->last_data_chunk_from == NULL) {
9891 /* Hmm we never received anything */
9892 return;
9893 }
9894 sctp_slide_mapping_arrays(stcb);
9886 sctp_set_rwnd(stcb, asoc);
9887 TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
9895 sctp_set_rwnd(stcb, asoc);
9896 TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
9888 if (chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) {
9897 if (chk->rec.chunk_id.id == type) {
9889 /* Hmm, found a sack already on queue, remove it */
9890 TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
9891 asoc->ctrl_queue_cnt++;
9892 a_chk = chk;
9893 if (a_chk->data) {
9894 sctp_m_freem(a_chk->data);
9895 a_chk->data = NULL;
9896 }

--- 12 unchanged lines hidden (view full) ---

9909 sctp_timer_start(SCTP_TIMER_TYPE_RECV,
9910 stcb->sctp_ep, stcb, NULL);
9911 } else {
9912 stcb->asoc.send_sack = 1;
9913 }
9914 return;
9915 }
9916 a_chk->copy_by_ref = 0;
9898 /* Hmm, found a sack already on queue, remove it */
9899 TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
9900 asoc->ctrl_queue_cnt++;
9901 a_chk = chk;
9902 if (a_chk->data) {
9903 sctp_m_freem(a_chk->data);
9904 a_chk->data = NULL;
9905 }

--- 12 unchanged lines hidden (view full) ---

9918 sctp_timer_start(SCTP_TIMER_TYPE_RECV,
9919 stcb->sctp_ep, stcb, NULL);
9920 } else {
9921 stcb->asoc.send_sack = 1;
9922 }
9923 return;
9924 }
9925 a_chk->copy_by_ref = 0;
9917 /* a_chk->rec.chunk_id.id = SCTP_SELECTIVE_ACK; */
9918 a_chk->rec.chunk_id.id = SCTP_SELECTIVE_ACK;
9926 a_chk->rec.chunk_id.id = type;
9919 a_chk->rec.chunk_id.can_take_data = 1;
9920 }
9921 /* Clear our pkt counts */
9922 asoc->data_pkts_seen = 0;
9923
9924 a_chk->asoc = asoc;
9925 a_chk->snd_count = 0;
9926 a_chk->send_size = 0; /* fill in later */

--- 35 unchanged lines hidden (view full) ---

9962 }
9963 if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
9964 highest_tsn = asoc->highest_tsn_inside_map;
9965 } else {
9966 highest_tsn = asoc->highest_tsn_inside_nr_map;
9967 }
9968 if (highest_tsn == asoc->cumulative_tsn) {
9969 /* no gaps */
9927 a_chk->rec.chunk_id.can_take_data = 1;
9928 }
9929 /* Clear our pkt counts */
9930 asoc->data_pkts_seen = 0;
9931
9932 a_chk->asoc = asoc;
9933 a_chk->snd_count = 0;
9934 a_chk->send_size = 0; /* fill in later */

--- 35 unchanged lines hidden (view full) ---

9970 }
9971 if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
9972 highest_tsn = asoc->highest_tsn_inside_map;
9973 } else {
9974 highest_tsn = asoc->highest_tsn_inside_nr_map;
9975 }
9976 if (highest_tsn == asoc->cumulative_tsn) {
9977 /* no gaps */
9970 space_req = sizeof(struct sctp_sack_chunk);
9978 if (type == SCTP_SELECTIVE_ACK) {
9979 space_req = sizeof(struct sctp_sack_chunk);
9980 } else {
9981 space_req = sizeof(struct sctp_nr_sack_chunk);
9982 }
9971 } else {
9972 /* gaps get a cluster */
9973 space_req = MCLBYTES;
9974 }
9975 /* Ok now lets formulate a MBUF with our sack */
9976 a_chk->data = sctp_get_mbuf_for_msg(space_req, 0, M_DONTWAIT, 1, MT_DATA);
9977 if ((a_chk->data == NULL) ||
9978 (a_chk->whoTo == NULL)) {

--- 19 unchanged lines hidden (view full) ---

9998 SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD);
9999 space = M_TRAILINGSPACE(a_chk->data);
10000 if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) {
10001 space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD);
10002 }
10003 limit = mtod(a_chk->data, caddr_t);
10004 limit += space;
10005
9983 } else {
9984 /* gaps get a cluster */
9985 space_req = MCLBYTES;
9986 }
9987 /* Ok now lets formulate a MBUF with our sack */
9988 a_chk->data = sctp_get_mbuf_for_msg(space_req, 0, M_DONTWAIT, 1, MT_DATA);
9989 if ((a_chk->data == NULL) ||
9990 (a_chk->whoTo == NULL)) {

--- 19 unchanged lines hidden (view full) ---

10010 SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD);
10011 space = M_TRAILINGSPACE(a_chk->data);
10012 if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) {
10013 space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD);
10014 }
10015 limit = mtod(a_chk->data, caddr_t);
10016 limit += space;
10017
10006 sack = mtod(a_chk->data, struct sctp_sack_chunk *);
10007 sack->ch.chunk_type = SCTP_SELECTIVE_ACK;
10008 /* 0x01 is used by nonce for ecn */
10009 if ((SCTP_BASE_SYSCTL(sctp_ecn_enable)) &&
10010 (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) &&
10011 (asoc->peer_supports_ecn_nonce))
10018 /* 0x01 is used by nonce for ecn */
10019 if ((SCTP_BASE_SYSCTL(sctp_ecn_enable)) &&
10020 (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) &&
10021 (asoc->peer_supports_ecn_nonce))
10012 sack->ch.chunk_flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
10022 flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
10013 else
10023 else
10014 sack->ch.chunk_flags = 0;
10024 flags = 0;
10015
10016 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
10017 /*-
10018 * CMT DAC algorithm: If 2 (i.e., 0x10) packets have been
10019 * received, then set high bit to 1, else 0. Reset
10020 * pkts_rcvd.
10021 */
10025
10026 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
10027 /*-
10028 * CMT DAC algorithm: If 2 (i.e., 0x10) packets have been
10029 * received, then set high bit to 1, else 0. Reset
10030 * pkts_rcvd.
10031 */
10022 sack->ch.chunk_flags |= (asoc->cmt_dac_pkts_rcvd << 6);
10032 flags |= (asoc->cmt_dac_pkts_rcvd << 6);
10023 asoc->cmt_dac_pkts_rcvd = 0;
10024 }
10025#ifdef SCTP_ASOCLOG_OF_TSNS
10026 stcb->asoc.cumack_logsnt[stcb->asoc.cumack_log_atsnt] = asoc->cumulative_tsn;
10027 stcb->asoc.cumack_log_atsnt++;
10028 if (stcb->asoc.cumack_log_atsnt >= SCTP_TSN_LOG_SIZE) {
10029 stcb->asoc.cumack_log_atsnt = 0;
10030 }
10031#endif
10033 asoc->cmt_dac_pkts_rcvd = 0;
10034 }
10035#ifdef SCTP_ASOCLOG_OF_TSNS
10036 stcb->asoc.cumack_logsnt[stcb->asoc.cumack_log_atsnt] = asoc->cumulative_tsn;
10037 stcb->asoc.cumack_log_atsnt++;
10038 if (stcb->asoc.cumack_log_atsnt >= SCTP_TSN_LOG_SIZE) {
10039 stcb->asoc.cumack_log_atsnt = 0;
10040 }
10041#endif
10032 sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
10033 sack->sack.a_rwnd = htonl(asoc->my_rwnd);
10034 asoc->my_last_reported_rwnd = asoc->my_rwnd;
10035
10036 /* reset the readers interpretation */
10037 stcb->freed_by_sorcv_sincelast = 0;
10038
10042 /* reset the readers interpretation */
10043 stcb->freed_by_sorcv_sincelast = 0;
10044
10039 gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk));
10040
10041 if (highest_tsn > asoc->mapping_array_base_tsn)
10042 siz = (((highest_tsn - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
10043 else
10044 siz = (((MAX_TSN - highest_tsn) + 1) + highest_tsn + 7) / 8;
10045
10046 if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
10047 offset = 1;
10048 /*-
10049 * cum-ack behind the mapping array, so we start and use all
10050 * entries.
10051 */
10052 jstart = 0;
10053 } else {
10054 offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
10055 /*-
10056 * we skip the first one when the cum-ack is at or above the
10057 * mapping array base. Note this only works if
10058 */
10059 jstart = 1;
10060 }
10061 if (compare_with_wrap(highest_tsn, asoc->cumulative_tsn, MAX_TSN)) {
10062 /* we have a gap .. maybe */
10063 for (i = 0; i < siz; i++) {
10064 selector = &sack_array[(asoc->mapping_array[i] | asoc->nr_mapping_array[i])];
10065 if (mergeable && selector->right_edge) {
10066 /*
10067 * Backup, left and right edges were ok to
10068 * merge.
10069 */
10070 num_gap_blocks--;
10071 gap_descriptor--;
10072 }
10073 if (selector->num_entries == 0)
10074 mergeable = 0;
10075 else {
10076 for (j = jstart; j < selector->num_entries; j++) {
10077 if (mergeable && selector->right_edge) {
10078 /*
10079 * do a merge by NOT setting
10080 * the left side
10081 */
10082 mergeable = 0;
10083 } else {
10084 /*
10085 * no merge, set the left
10086 * side
10087 */
10088 mergeable = 0;
10089 gap_descriptor->start = htons((selector->gaps[j].start + offset));
10090 }
10091 gap_descriptor->end = htons((selector->gaps[j].end + offset));
10092 num_gap_blocks++;
10093 gap_descriptor++;
10094 if (((caddr_t)gap_descriptor + sizeof(struct sctp_gap_ack_block)) > limit) {
10095 /* no more room */
10096 limit_reached = 1;
10097 break;
10098 }
10099 }
10100 if (selector->left_edge) {
10101 mergeable = 1;
10102 }
10103 }
10104 if (limit_reached) {
10105 /* Reached the limit stop */
10106 break;
10107 }
10108 jstart = 0;
10109 offset += 8;
10110 }
10111 if (num_gap_blocks == 0) {
10112 /*
10113 * slide not yet happened, and somehow we got called
10114 * to send a sack. Cumack needs to move up.
10115 */
10116 int abort_flag = 0;
10117
10118 sctp_sack_check(stcb, 0, 0, &abort_flag);
10119 }
10120 }
10121 /* now we must add any dups we are going to report. */
10122 if ((limit_reached == 0) && (asoc->numduptsns)) {
10123 dup = (uint32_t *) gap_descriptor;
10124 for (i = 0; i < asoc->numduptsns; i++) {
10125 *dup = htonl(asoc->dup_tsns[i]);
10126 dup++;
10127 num_dups++;
10128 if (((caddr_t)dup + sizeof(uint32_t)) > limit) {
10129 /* no more room */
10130 break;
10131 }
10132 }
10133 asoc->numduptsns = 0;
10134 }
10135 /*
10136 * now that the chunk is prepared queue it to the control chunk
10137 * queue.
10138 */
10139 a_chk->send_size = (sizeof(struct sctp_sack_chunk) +
10140 (num_gap_blocks * sizeof(struct sctp_gap_ack_block)) +
10141 (num_dups * sizeof(int32_t)));
10142 SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
10143 sack->sack.num_gap_ack_blks = htons(num_gap_blocks);
10144 sack->sack.num_dup_tsns = htons(num_dups);
10145 sack->ch.chunk_length = htons(a_chk->send_size);
10146 TAILQ_INSERT_TAIL(&asoc->control_send_queue, a_chk, sctp_next);
10147 asoc->ctrl_queue_cnt++;
10148 asoc->send_sack = 0;
10149 SCTP_STAT_INCR(sctps_sendsacks);
10150 return;
10151}
10152
10153/* EY - This method will replace sctp_send_sack method if nr_sacks negotiated*/
10154void
10155sctp_send_nr_sack(struct sctp_tcb *stcb)
10156{
10157 /*-
10158 * Queue up an NR-SACK in the control queue. We must first check to see
10159 * if an NR-SACK is somehow on the control queue. If so, we will take
10160 * and and remove the old one.
10161 */
10162 struct sctp_association *asoc;
10163 struct sctp_tmit_chunk *chk, *a_chk;
10164
10165 struct sctp_nr_sack_chunk *nr_sack;
10166
10167 struct sctp_gap_ack_block *gap_descriptor;
10168
10169 struct sack_track *selector;
10170 struct sack_track *nr_selector;
10171
10172 /* EY do we need nr_mergeable, NO */
10173 int mergeable = 0;
10174 int offset;
10175 caddr_t limit;
10176 uint32_t *dup, highest_tsn;
10177 int limit_reached = 0;
10178 int seen_non_zero = 0;
10179 unsigned int i, jstart, siz, j;
10180 unsigned int num_gap_blocks = 0, num_nr_gap_blocks = 0, space;
10181 int num_dups = 0;
10182 int space_req;
10183
10184 a_chk = NULL;
10185 asoc = &stcb->asoc;
10186 SCTP_TCB_LOCK_ASSERT(stcb);
10187 if (asoc->last_data_chunk_from == NULL) {
10188 /* Hmm we never received anything */
10189 return;
10190 }
10191 sctp_set_rwnd(stcb, asoc);
10192 TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
10193 if (chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK) {
10194 /* Hmm, found a sack already on queue, remove it */
10195 TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
10196 asoc->ctrl_queue_cnt++;
10197 a_chk = chk;
10198 if (a_chk->data) {
10199 sctp_m_freem(a_chk->data);
10200 a_chk->data = NULL;
10201 }
10202 sctp_free_remote_addr(a_chk->whoTo);
10203 a_chk->whoTo = NULL;
10204 break;
10205 }
10206 }
10207 if (a_chk == NULL) {
10208 sctp_alloc_a_chunk(stcb, a_chk);
10209 if (a_chk == NULL) {
10210 /* No memory so we drop the idea, and set a timer */
10211 if (stcb->asoc.delayed_ack) {
10212 sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
10213 stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_5);
10214 sctp_timer_start(SCTP_TIMER_TYPE_RECV,
10215 stcb->sctp_ep, stcb, NULL);
10216 } else {
10217 stcb->asoc.send_sack = 1;
10218 }
10219 return;
10220 }
10221 a_chk->copy_by_ref = 0;
10222 /* a_chk->rec.chunk_id.id = SCTP_SELECTIVE_ACK; */
10223 a_chk->rec.chunk_id.id = SCTP_NR_SELECTIVE_ACK;
10224 a_chk->rec.chunk_id.can_take_data = 1;
10225 }
10226 /* Clear our pkt counts */
10227 asoc->data_pkts_seen = 0;
10228
10229 a_chk->asoc = asoc;
10230 a_chk->snd_count = 0;
10231 a_chk->send_size = 0; /* fill in later */
10232 a_chk->sent = SCTP_DATAGRAM_UNSENT;
10233 a_chk->whoTo = NULL;
10234
10235 if ((asoc->numduptsns) ||
10236 (asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)
10237 ) {
10238 /*-
10239 * Ok, we have some duplicates or the destination for the
10240 * sack is unreachable, lets see if we can select an
10241 * alternate than asoc->last_data_chunk_from
10242 */
10243 if ((!(asoc->last_data_chunk_from->dest_state &
10244 SCTP_ADDR_NOT_REACHABLE)) &&
10245 (asoc->used_alt_onsack > asoc->numnets)) {
10246 /* We used an alt last time, don't this time */
10247 a_chk->whoTo = NULL;
10045 if (type == SCTP_SELECTIVE_ACK) {
10046 sack = mtod(a_chk->data, struct sctp_sack_chunk *);
10047 nr_sack = NULL;
10048 gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk));
10049 if (highest_tsn > asoc->mapping_array_base_tsn) {
10050 siz = (((highest_tsn - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
10248 } else {
10051 } else {
10249 asoc->used_alt_onsack++;
10250 a_chk->whoTo = sctp_find_alternate_net(stcb, asoc->last_data_chunk_from, 0);
10052 siz = (((MAX_TSN - highest_tsn) + 1) + highest_tsn + 7) / 8;
10251 }
10053 }
10252 if (a_chk->whoTo == NULL) {
10253 /* Nope, no alternate */
10254 a_chk->whoTo = asoc->last_data_chunk_from;
10255 asoc->used_alt_onsack = 0;
10256 }
10257 } else {
10054 } else {
10258 /*
10259 * No duplicates so we use the last place we received data
10260 * from.
10261 */
10262 asoc->used_alt_onsack = 0;
10263 a_chk->whoTo = asoc->last_data_chunk_from;
10264 }
10265 if (a_chk->whoTo) {
10266 atomic_add_int(&a_chk->whoTo->ref_count, 1);
10267 }
10268 if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
10269 highest_tsn = asoc->highest_tsn_inside_map;
10270 } else {
10271 highest_tsn = asoc->highest_tsn_inside_nr_map;
10272 }
10273 if (highest_tsn == asoc->cumulative_tsn) {
10274 /* no gaps */
10275 space_req = sizeof(struct sctp_nr_sack_chunk);
10276 } else {
10277 /* EY - what is this about? */
10278 /* gaps get a cluster */
10279 space_req = MCLBYTES;
10280 }
10281 /* Ok now lets formulate a MBUF with our sack */
10282 a_chk->data = sctp_get_mbuf_for_msg(space_req, 0, M_DONTWAIT, 1, MT_DATA);
10283 if ((a_chk->data == NULL) ||
10284 (a_chk->whoTo == NULL)) {
10285 /* rats, no mbuf memory */
10286 if (a_chk->data) {
10287 /* was a problem with the destination */
10288 sctp_m_freem(a_chk->data);
10289 a_chk->data = NULL;
10290 }
10291 sctp_free_a_chunk(stcb, a_chk);
10292 /* sa_ignore NO_NULL_CHK */
10293 if (stcb->asoc.delayed_ack) {
10294 sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
10295 stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_6);
10296 sctp_timer_start(SCTP_TIMER_TYPE_RECV,
10297 stcb->sctp_ep, stcb, NULL);
10055 sack = NULL;
10056 nr_sack = mtod(a_chk->data, struct sctp_nr_sack_chunk *);
10057 gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)nr_sack + sizeof(struct sctp_nr_sack_chunk));
10058 if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn) {
10059 siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
10298 } else {
10060 } else {
10299 stcb->asoc.send_sack = 1;
10061 siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8;
10300 }
10062 }
10301 return;
10302 }
10063 }
10303 /* ok, lets go through and fill it in */
10304 SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD);
10305 space = M_TRAILINGSPACE(a_chk->data);
10306 if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) {
10307 space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD);
10308 }
10309 limit = mtod(a_chk->data, caddr_t);
10310 limit += space;
10311
10064
10312 nr_sack = mtod(a_chk->data, struct sctp_nr_sack_chunk *);
10313 nr_sack->ch.chunk_type = SCTP_NR_SELECTIVE_ACK;
10314 /* EYJ */
10315 /* 0x01 is used by nonce for ecn */
10316 if ((SCTP_BASE_SYSCTL(sctp_ecn_enable)) &&
10317 (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) &&
10318 (asoc->peer_supports_ecn_nonce))
10319 nr_sack->ch.chunk_flags = (asoc->receiver_nonce_sum & SCTP_SACK_NONCE_SUM);
10320 else
10321 nr_sack->ch.chunk_flags = 0;
10322
10323 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) && SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
10324 /*-
10325 * CMT DAC algorithm: If 2 (i.e., 0x10) packets have been
10326 * received, then set high bit to 1, else 0. Reset
10327 * pkts_rcvd.
10328 */
10329 /* EY - TODO: which chunk flag is used in here? -The LSB */
10330 nr_sack->ch.chunk_flags |= (asoc->cmt_dac_pkts_rcvd << 6);
10331 asoc->cmt_dac_pkts_rcvd = 0;
10332 }
10333#ifdef SCTP_ASOCLOG_OF_TSNS
10334 stcb->asoc.cumack_logsnt[stcb->asoc.cumack_log_atsnt] = asoc->cumulative_tsn;
10335 stcb->asoc.cumack_log_atsnt++;
10336 if (stcb->asoc.cumack_log_atsnt >= SCTP_TSN_LOG_SIZE) {
10337 stcb->asoc.cumack_log_atsnt = 0;
10338 }
10339#endif
10340 nr_sack->nr_sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
10341 nr_sack->nr_sack.a_rwnd = htonl(asoc->my_rwnd);
10342 asoc->my_last_reported_rwnd = asoc->my_rwnd;
10343
10344 /* reset the readers interpretation */
10345 stcb->freed_by_sorcv_sincelast = 0;
10346
10347 gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)nr_sack + sizeof(struct sctp_nr_sack_chunk));
10348
10349 if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn)
10350 siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
10351 else
10352 siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8;
10353
10354 if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
10355 offset = 1;
10356 /*-
10065 if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
10066 offset = 1;
10067 /*-
10357 * cum-ack behind the mapping array, so we start and use all
10358 * entries.
10068 * The base TSN is intialized to be the first TSN the peer
10069 * will send us. If the cum-ack is behind this then when they
10070 * send us the next in sequence it will mark the base_tsn bit.
10071 * Thus we need to use the very first selector and the offset
10072 * is 1. Our table is built for this case.
10359 */
10073 */
10360 jstart = 0;
10074 starting_index = 0;
10075 sel_start = 0;
10361 } else {
10076 } else {
10362 offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
10363 /*-
10077 /*-
10364 * we skip the first one when the cum-ack is at or above the
10365 * mapping array base. Note this only works if
10078 * we skip the first selector when the cum-ack is at or above the
10079 * mapping array base. This is because the bits at the base or above
10080 * are turned on and our first selector in the table assumes they are
10081 * off. We thus will use the second selector (first is 0). We use
10082 * the reverse of our macro to fix the offset, in bits, that our
10083 * table is at. Note that this method assumes that the cum-tsn is
10084 * within the first bit, i.e. its value is 0-7 which means the
10085 * result to our offset will be either a 0 - -7. If the cumack
10086 * is NOT in the first byte (0) (which it should be since we did
10087 * a mapping array slide above) then we need to calculate the starting
10088 * index i.e. which byte of the mapping array we should start at. We
10089 * do this by dividing by 8 and pushing the remainder (mod) into offset.
10090 * then we multiply the offset to be negative, since we need a negative
10091 * offset into the selector table.
10366 */
10092 */
10367 jstart = 1;
10093 SCTP_CALC_TSN_TO_GAP(offset, asoc->cumulative_tsn, asoc->mapping_array_base_tsn);
10094 if (offset > 7) {
10095 starting_index = offset / 8;
10096 offset = offset % 8;
10097 printf("Strange starting index is %d offset:%d (not 0/x)\n",
10098 starting_index, offset);
10099 } else {
10100 starting_index = 0;
10101 }
10102 /* We need a negative offset in our table */
10103 offset *= -1;
10104 sel_start = 1;
10368 }
10105 }
10369 if (compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN)) {
10106 if (((type == SCTP_SELECTIVE_ACK) &&
10107 compare_with_wrap(highest_tsn, asoc->cumulative_tsn, MAX_TSN)) ||
10108 ((type == SCTP_NR_SELECTIVE_ACK) &&
10109 compare_with_wrap(asoc->highest_tsn_inside_map, asoc->cumulative_tsn, MAX_TSN))) {
10370 /* we have a gap .. maybe */
10110 /* we have a gap .. maybe */
10371 for (i = 0; i < siz; i++) {
10372 seen_non_zero = 1;
10373 selector = &sack_array[asoc->mapping_array[i]];
10111 for (i = starting_index; i < siz; i++) {
10112 if (type == SCTP_SELECTIVE_ACK) {
10113 selector = &sack_array[asoc->mapping_array[i] | asoc->nr_mapping_array[i]];
10114 } else {
10115 selector = &sack_array[asoc->mapping_array[i]];
10116 }
10374 if (mergeable && selector->right_edge) {
10375 /*
10376 * Backup, left and right edges were ok to
10377 * merge.
10378 */
10379 num_gap_blocks--;
10380 gap_descriptor--;
10381 }
10382 if (selector->num_entries == 0)
10383 mergeable = 0;
10384 else {
10117 if (mergeable && selector->right_edge) {
10118 /*
10119 * Backup, left and right edges were ok to
10120 * merge.
10121 */
10122 num_gap_blocks--;
10123 gap_descriptor--;
10124 }
10125 if (selector->num_entries == 0)
10126 mergeable = 0;
10127 else {
10385 for (j = jstart; j < selector->num_entries; j++) {
10128 for (j = sel_start; j < selector->num_entries; j++) {
10386 if (mergeable && selector->right_edge) {
10387 /*
10388 * do a merge by NOT setting
10389 * the left side
10390 */
10391 mergeable = 0;
10392 } else {
10393 /*

--- 15 unchanged lines hidden (view full) ---

10409 if (selector->left_edge) {
10410 mergeable = 1;
10411 }
10412 }
10413 if (limit_reached) {
10414 /* Reached the limit stop */
10415 break;
10416 }
10129 if (mergeable && selector->right_edge) {
10130 /*
10131 * do a merge by NOT setting
10132 * the left side
10133 */
10134 mergeable = 0;
10135 } else {
10136 /*

--- 15 unchanged lines hidden (view full) ---

10152 if (selector->left_edge) {
10153 mergeable = 1;
10154 }
10155 }
10156 if (limit_reached) {
10157 /* Reached the limit stop */
10158 break;
10159 }
10417 jstart = 0;
10160 sel_start = 0;
10418 offset += 8;
10419 }
10420 }
10161 offset += 8;
10162 }
10163 }
10421 if (limit_reached == 0) {
10164 if ((type == SCTP_NR_SELECTIVE_ACK) &&
10165 (limit_reached == 0)) {
10422
10423 mergeable = 0;
10424
10166
10167 mergeable = 0;
10168
10425 if (asoc->highest_tsn_inside_nr_map > asoc->nr_mapping_array_base_tsn)
10426 siz = (((asoc->highest_tsn_inside_nr_map - asoc->nr_mapping_array_base_tsn) + 1) + 7) / 8;
10169 if (asoc->highest_tsn_inside_nr_map > asoc->mapping_array_base_tsn)
10170 siz = (((asoc->highest_tsn_inside_nr_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
10427 else
10171 else
10428 siz = (((MAX_TSN - asoc->nr_mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_nr_map + 7) / 8;
10172 siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_nr_map + 7) / 8;
10429
10173
10430 if (compare_with_wrap(asoc->nr_mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
10174 if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
10431 offset = 1;
10432 /*-
10433 * cum-ack behind the mapping array, so we start and use all
10434 * entries.
10435 */
10175 offset = 1;
10176 /*-
10177 * cum-ack behind the mapping array, so we start and use all
10178 * entries.
10179 */
10436 jstart = 0;
10180 sel_start = 0;
10437 } else {
10181 } else {
10438 offset = asoc->nr_mapping_array_base_tsn - asoc->cumulative_tsn;
10182 offset = asoc->mapping_array_base_tsn - asoc->cumulative_tsn;
10439 /*-
10440 * we skip the first one when the cum-ack is at or above the
10441 * mapping array base. Note this only works if
10442 */
10183 /*-
10184 * we skip the first one when the cum-ack is at or above the
10185 * mapping array base. Note this only works if
10186 */
10443 jstart = 1;
10187 sel_start = 1;
10444 }
10445 if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn, MAX_TSN)) {
10446 /* we have a gap .. maybe */
10447 for (i = 0; i < siz; i++) {
10188 }
10189 if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn, MAX_TSN)) {
10190 /* we have a gap .. maybe */
10191 for (i = 0; i < siz; i++) {
10448 nr_selector = &sack_array[asoc->nr_mapping_array[i]];
10449 if (mergeable && nr_selector->right_edge) {
10192 selector = &sack_array[asoc->nr_mapping_array[i]];
10193 if (mergeable && selector->right_edge) {
10450 /*
10451 * Backup, left and right edges were
10452 * ok to merge.
10453 */
10454 num_nr_gap_blocks--;
10455 gap_descriptor--;
10456 }
10194 /*
10195 * Backup, left and right edges were
10196 * ok to merge.
10197 */
10198 num_nr_gap_blocks--;
10199 gap_descriptor--;
10200 }
10457 if (nr_selector->num_entries == 0)
10201 if (selector->num_entries == 0)
10458 mergeable = 0;
10459 else {
10202 mergeable = 0;
10203 else {
10460 for (j = jstart; j < nr_selector->num_entries; j++) {
10461 if (mergeable && nr_selector->right_edge) {
10204 for (j = sel_start; j < selector->num_entries; j++) {
10205 if (mergeable && selector->right_edge) {
10462 /*
10463 * do a merge by NOT
10464 * setting the left
10465 * side
10466 */
10467 mergeable = 0;
10468 } else {
10469 /*
10470 * no merge, set the
10471 * left side
10472 */
10473 mergeable = 0;
10206 /*
10207 * do a merge by NOT
10208 * setting the left
10209 * side
10210 */
10211 mergeable = 0;
10212 } else {
10213 /*
10214 * no merge, set the
10215 * left side
10216 */
10217 mergeable = 0;
10474 gap_descriptor->start = htons((nr_selector->gaps[j].start + offset));
10218 gap_descriptor->start = htons((selector->gaps[j].start + offset));
10475 }
10219 }
10476 gap_descriptor->end = htons((nr_selector->gaps[j].end + offset));
10220 gap_descriptor->end = htons((selector->gaps[j].end + offset));
10477 num_nr_gap_blocks++;
10478 gap_descriptor++;
10479 if (((caddr_t)gap_descriptor + sizeof(struct sctp_gap_ack_block)) > limit) {
10480 /* no more room */
10481 limit_reached = 1;
10482 break;
10483 }
10484 }
10221 num_nr_gap_blocks++;
10222 gap_descriptor++;
10223 if (((caddr_t)gap_descriptor + sizeof(struct sctp_gap_ack_block)) > limit) {
10224 /* no more room */
10225 limit_reached = 1;
10226 break;
10227 }
10228 }
10485 if (nr_selector->left_edge) {
10229 if (selector->left_edge) {
10486 mergeable = 1;
10487 }
10488 }
10489 if (limit_reached) {
10490 /* Reached the limit stop */
10491 break;
10492 }
10230 mergeable = 1;
10231 }
10232 }
10233 if (limit_reached) {
10234 /* Reached the limit stop */
10235 break;
10236 }
10493 jstart = 0;
10237 sel_start = 0;
10494 offset += 8;
10495 }
10496 }
10497 }
10238 offset += 8;
10239 }
10240 }
10241 }
10242 /* now we must add any dups we are going to report. */
10498 if ((limit_reached == 0) && (asoc->numduptsns)) {
10499 dup = (uint32_t *) gap_descriptor;
10500 for (i = 0; i < asoc->numduptsns; i++) {
10501 *dup = htonl(asoc->dup_tsns[i]);
10502 dup++;
10503 num_dups++;
10504 if (((caddr_t)dup + sizeof(uint32_t)) > limit) {
10505 /* no more room */
10506 break;
10507 }
10508 }
10509 asoc->numduptsns = 0;
10510 }
10511 /*
10512 * now that the chunk is prepared queue it to the control chunk
10513 * queue.
10514 */
10243 if ((limit_reached == 0) && (asoc->numduptsns)) {
10244 dup = (uint32_t *) gap_descriptor;
10245 for (i = 0; i < asoc->numduptsns; i++) {
10246 *dup = htonl(asoc->dup_tsns[i]);
10247 dup++;
10248 num_dups++;
10249 if (((caddr_t)dup + sizeof(uint32_t)) > limit) {
10250 /* no more room */
10251 break;
10252 }
10253 }
10254 asoc->numduptsns = 0;
10255 }
10256 /*
10257 * now that the chunk is prepared queue it to the control chunk
10258 * queue.
10259 */
10515 a_chk->send_size = sizeof(struct sctp_nr_sack_chunk) +
10516 (num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
10517 num_dups * sizeof(int32_t);
10518
10519 SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
10520 nr_sack->nr_sack.num_gap_ack_blks = htons(num_gap_blocks);
10521 nr_sack->nr_sack.num_nr_gap_ack_blks = htons(num_nr_gap_blocks);
10522 nr_sack->nr_sack.num_dup_tsns = htons(num_dups);
10523 nr_sack->nr_sack.reserved = 0;
10524 nr_sack->ch.chunk_length = htons(a_chk->send_size);
10260 if (type == SCTP_SELECTIVE_ACK) {
10261 a_chk->send_size = sizeof(struct sctp_sack_chunk) +
10262 (num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
10263 num_dups * sizeof(int32_t);
10264 SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
10265 sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
10266 sack->sack.a_rwnd = htonl(asoc->my_rwnd);
10267 sack->sack.num_gap_ack_blks = htons(num_gap_blocks);
10268 sack->sack.num_dup_tsns = htons(num_dups);
10269 sack->ch.chunk_type = type;
10270 sack->ch.chunk_flags = flags;
10271 sack->ch.chunk_length = htons(a_chk->send_size);
10272 } else {
10273 a_chk->send_size = sizeof(struct sctp_nr_sack_chunk) +
10274 (num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
10275 num_dups * sizeof(int32_t);
10276 SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
10277 nr_sack->nr_sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
10278 nr_sack->nr_sack.a_rwnd = htonl(asoc->my_rwnd);
10279 nr_sack->nr_sack.num_gap_ack_blks = htons(num_gap_blocks);
10280 nr_sack->nr_sack.num_nr_gap_ack_blks = htons(num_nr_gap_blocks);
10281 nr_sack->nr_sack.num_dup_tsns = htons(num_dups);
10282 nr_sack->nr_sack.reserved = 0;
10283 nr_sack->ch.chunk_type = type;
10284 nr_sack->ch.chunk_flags = flags;
10285 nr_sack->ch.chunk_length = htons(a_chk->send_size);
10286 }
10525 TAILQ_INSERT_TAIL(&asoc->control_send_queue, a_chk, sctp_next);
10287 TAILQ_INSERT_TAIL(&asoc->control_send_queue, a_chk, sctp_next);
10288 asoc->my_last_reported_rwnd = asoc->my_rwnd;
10526 asoc->ctrl_queue_cnt++;
10527 asoc->send_sack = 0;
10528 SCTP_STAT_INCR(sctps_sendsacks);
10529 return;
10530}
10531
10532void
10533sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked

--- 2037 unchanged lines hidden (view full) ---

12571 }
12572 /* get an asoc/stcb struct */
12573 vrf_id = inp->def_vrf_id;
12574#ifdef INVARIANTS
12575 if (create_lock_applied == 0) {
12576 panic("Error, should hold create lock and I don't?");
12577 }
12578#endif
10289 asoc->ctrl_queue_cnt++;
10290 asoc->send_sack = 0;
10291 SCTP_STAT_INCR(sctps_sendsacks);
10292 return;
10293}
10294
10295void
10296sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked

--- 2037 unchanged lines hidden (view full) ---

12334 }
12335 /* get an asoc/stcb struct */
12336 vrf_id = inp->def_vrf_id;
12337#ifdef INVARIANTS
12338 if (create_lock_applied == 0) {
12339 panic("Error, should hold create lock and I don't?");
12340 }
12341#endif
12579 stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id,
12342 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
12580 p
12581 );
12582 if (stcb == NULL) {
12583 /* Error is setup for us in the call */
12584 goto out_unlocked;
12585 }
12586 if (create_lock_applied) {
12587 SCTP_ASOC_CREATE_UNLOCK(inp);

--- 1193 unchanged lines hidden ---
12343 p
12344 );
12345 if (stcb == NULL) {
12346 /* Error is setup for us in the call */
12347 goto out_unlocked;
12348 }
12349 if (create_lock_applied) {
12350 SCTP_ASOC_CREATE_UNLOCK(inp);

--- 1193 unchanged lines hidden ---