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 --- |