- fix source address selection when picking an acceptable address
- name change of prefered -> preferred - CMT fast recover code added. - Comment fixes in CMT. - We were not giving a reason of cant_start_asoc per socket api if we failed to get init/or/cookie to bring up an assoc. Change so we don't just give a generic "comm lost" but look at actual states of dying assoc. - change "crc32" arguments to "crc32c" to silence strict/noisy compiler warnings when crc32() is also declared - A few minor tweaks to get the portable stuff truely portable for sctp6_usrreq.c :-D - one-2-one style vrf match problem. - window recovery would leave chks marked for retran during window probes on the sent queue. This would then cause an out-of-order problem and assure that the flight size "problem" would occur. - Solves a flight size logging issue that caused rwnd overruns, flight size off as well as false retransmissions.g - Macroize the up and down of flight size. - Fix a ECNE bug in its counting. - The strict_sacks options was causing aborts when window probing was active, fix to make strict sacks a bit smarter about what the next unsent TSN is. - Fixes a one-2-one wakeup bug found by Martin Kulas. - If-defed out form, Andre's copy routines pending his commit of at least m_last().. need to adjust for 6.2 as well.. since m_last won't exist. Reviewed by: gnn
This commit is contained in:
parent
fac89d2743
commit
c105859eee
@ -186,9 +186,17 @@ __FBSDID("$FreeBSD$");
|
||||
#define SCTP_RANDY_STUFF1 103
|
||||
#define SCTP_STRMOUT_LOG_ASSIGN 104
|
||||
#define SCTP_STRMOUT_LOG_SEND 105
|
||||
#define SCTP_FLIGHT_LOG_DOWN 106
|
||||
#define SCTP_FLIGHT_LOG_DOWN_CA 106
|
||||
#define SCTP_FLIGHT_LOG_UP 107
|
||||
#define SCTP_LOG_MAX_TYPES 108
|
||||
#define SCTP_FLIGHT_LOG_DOWN_GAP 108
|
||||
#define SCTP_FLIGHT_LOG_DOWN_RSND 109
|
||||
#define SCTP_FLIGHT_LOG_UP_RSND 110
|
||||
#define SCTP_FLIGHT_LOG_DOWN_RSND_TO 111
|
||||
#define SCTP_FLIGHT_LOG_DOWN_WP 112
|
||||
#define SCTP_FLIGHT_LOG_UP_REVOKE 113
|
||||
#define SCTP_FLIGHT_LOG_DOWN_PDRP 114
|
||||
#define SCTP_FLIGHT_LOG_DOWN_PMTU 115
|
||||
#define SCTP_LOG_MAX_TYPES 116
|
||||
/*
|
||||
* To turn on various logging, you must first define SCTP_STAT_LOGGING. Then
|
||||
* to get something to log you define one of the logging defines i.e.
|
||||
|
@ -579,17 +579,17 @@ sctp_crc32c_sb8_64_bit(uint32_t crc,
|
||||
* none
|
||||
*/
|
||||
uint32_t
|
||||
update_crc32(uint32_t crc32,
|
||||
update_crc32(uint32_t crc32c,
|
||||
unsigned char *buffer,
|
||||
unsigned int length)
|
||||
{
|
||||
uint32_t offset;
|
||||
|
||||
if (length == 0) {
|
||||
return (crc32);
|
||||
return (crc32c);
|
||||
}
|
||||
offset = ((uintptr_t) buffer) & 0x3;
|
||||
return (sctp_crc32c_sb8_64_bit(crc32, buffer, length, offset));
|
||||
return (sctp_crc32c_sb8_64_bit(crc32c, buffer, length, offset));
|
||||
}
|
||||
|
||||
uint32_t sctp_crc_c[256] = {
|
||||
@ -663,21 +663,21 @@ uint32_t sctp_crc_c[256] = {
|
||||
#define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF])
|
||||
|
||||
uint32_t
|
||||
old_update_crc32(uint32_t crc32,
|
||||
old_update_crc32(uint32_t crc32c,
|
||||
unsigned char *buffer,
|
||||
unsigned int length)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
SCTP_CRC32C(crc32, buffer[i]);
|
||||
SCTP_CRC32C(crc32c, buffer[i]);
|
||||
}
|
||||
return (crc32);
|
||||
return (crc32c);
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
sctp_csum_finalize(uint32_t crc32)
|
||||
sctp_csum_finalize(uint32_t crc32c)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
@ -686,7 +686,7 @@ sctp_csum_finalize(uint32_t crc32)
|
||||
|
||||
#endif
|
||||
/* Complement the result */
|
||||
result = ~crc32;
|
||||
result = ~crc32c;
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/*
|
||||
* For BIG-ENDIAN.. aka Motorola byte order the result is in
|
||||
@ -697,16 +697,16 @@ sctp_csum_finalize(uint32_t crc32)
|
||||
byte1 = (result >> 8) & 0x000000ff;
|
||||
byte2 = (result >> 16) & 0x000000ff;
|
||||
byte3 = (result >> 24) & 0x000000ff;
|
||||
crc32 = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
|
||||
crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
|
||||
#else
|
||||
/*
|
||||
* For INTEL platforms the result comes out in network order. No
|
||||
* htonl is required or the swap above. So we optimize out both the
|
||||
* htonl and the manual swap above.
|
||||
*/
|
||||
crc32 = result;
|
||||
crc32c = result;
|
||||
#endif
|
||||
return (crc32);
|
||||
return (crc32c);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2881,18 +2881,13 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
* value to the sender's
|
||||
* nonce sum
|
||||
*/
|
||||
if (tp1->sent < SCTP_DATAGRAM_ACKED) {
|
||||
/*
|
||||
* If it is less
|
||||
* than ACKED, it is
|
||||
* now no-longer in
|
||||
* flight. Higher
|
||||
* values may
|
||||
* already be set
|
||||
* via previous Gap
|
||||
* Ack Blocks...
|
||||
* i.e. ACKED or
|
||||
* MARKED.
|
||||
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
|
||||
/*-
|
||||
* If it is less than RESEND, it is
|
||||
* now no-longer in flight.
|
||||
* Higher values may already be set
|
||||
* via previous Gap Ack Blocks...
|
||||
* i.e. ACKED or RESEND.
|
||||
*/
|
||||
if (compare_with_wrap(tp1->rec.data.TSN_seq,
|
||||
*biggest_newly_acked_tsn, MAX_TSN)) {
|
||||
@ -2927,7 +2922,7 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
if (*this_sack_lowest_newack == 0) {
|
||||
#ifdef SCTP_SACK_LOGGING
|
||||
sctp_log_sack(*this_sack_lowest_newack,
|
||||
last_tsn,
|
||||
v last_tsn,
|
||||
tp1->rec.data.TSN_seq,
|
||||
0,
|
||||
0,
|
||||
@ -2985,28 +2980,16 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
SCTP_LOG_TSN_ACKED);
|
||||
#endif
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) stcb,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size)
|
||||
tp1->whoTo->flight_size -= tp1->book_size;
|
||||
else
|
||||
tp1->whoTo->flight_size = 0;
|
||||
|
||||
if (asoc->total_flight >= tp1->book_size) {
|
||||
asoc->total_flight -= tp1->book_size;
|
||||
if (asoc->total_flight_count > 0)
|
||||
asoc->total_flight_count--;
|
||||
} else {
|
||||
asoc->total_flight = 0;
|
||||
asoc->total_flight_count = 0;
|
||||
}
|
||||
sctp_flight_size_decrease(tp1);
|
||||
sctp_total_flight_decrease(stcb, tp1);
|
||||
|
||||
tp1->whoTo->net_ack += tp1->send_size;
|
||||
|
||||
if (tp1->snd_count < 2) {
|
||||
/*
|
||||
* True
|
||||
@ -3028,25 +3011,28 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tp1->sent <= SCTP_DATAGRAM_RESEND &&
|
||||
tp1->sent != SCTP_DATAGRAM_UNSENT &&
|
||||
compare_with_wrap(tp1->rec.data.TSN_seq,
|
||||
asoc->this_sack_highest_gap,
|
||||
MAX_TSN)) {
|
||||
asoc->this_sack_highest_gap =
|
||||
tp1->rec.data.TSN_seq;
|
||||
}
|
||||
if (tp1->sent == SCTP_DATAGRAM_RESEND) {
|
||||
sctp_ucount_decr(asoc->sent_queue_retran_cnt);
|
||||
if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
|
||||
(*ecn_seg_sums) += tp1->rec.data.ect_nonce;
|
||||
(*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
|
||||
if (compare_with_wrap(tp1->rec.data.TSN_seq,
|
||||
asoc->this_sack_highest_gap,
|
||||
MAX_TSN)) {
|
||||
asoc->this_sack_highest_gap =
|
||||
tp1->rec.data.TSN_seq;
|
||||
}
|
||||
if (tp1->sent == SCTP_DATAGRAM_RESEND) {
|
||||
sctp_ucount_decr(asoc->sent_queue_retran_cnt);
|
||||
#ifdef SCTP_AUDITING_ENABLED
|
||||
sctp_audit_log(0xB2,
|
||||
(asoc->sent_queue_retran_cnt & 0x000000ff));
|
||||
sctp_audit_log(0xB2,
|
||||
(asoc->sent_queue_retran_cnt & 0x000000ff));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
(*ecn_seg_sums) += tp1->rec.data.ect_nonce;
|
||||
(*ecn_seg_sums) &= SCTP_SACK_NONCE_SUM;
|
||||
|
||||
/*
|
||||
* All chunks NOT UNSENT
|
||||
* fall through here and are
|
||||
* marked
|
||||
*/
|
||||
tp1->sent = SCTP_DATAGRAM_MARKED;
|
||||
if (tp1->rec.data.chunk_was_revoked) {
|
||||
/* deflate the cwnd */
|
||||
@ -3074,7 +3060,8 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
}
|
||||
|
||||
static void
|
||||
sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack,
|
||||
sctp_check_for_revoked(struct sctp_tcb *stcb,
|
||||
struct sctp_association *asoc, uint32_t cumack,
|
||||
u_long biggest_tsn_acked)
|
||||
{
|
||||
struct sctp_tmit_chunk *tp1;
|
||||
@ -3098,15 +3085,20 @@ sctp_check_for_revoked(struct sctp_association *asoc, uint32_t cumack,
|
||||
* We must add this stuff back in to assure
|
||||
* timers and such get started.
|
||||
*/
|
||||
tp1->whoTo->flight_size += tp1->book_size;
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
sctp_flight_size_increase(tp1);
|
||||
sctp_total_flight_increase(stcb, tp1);
|
||||
/*
|
||||
* We inflate the cwnd to compensate for our
|
||||
* artificial inflation of the flight_size.
|
||||
*/
|
||||
tp1->whoTo->cwnd += tp1->book_size;
|
||||
asoc->total_flight_count++;
|
||||
asoc->total_flight += tp1->book_size;
|
||||
|
||||
tot_revoked++;
|
||||
#ifdef SCTP_SACK_LOGGING
|
||||
sctp_log_sack(asoc->last_acked_seq,
|
||||
@ -3247,8 +3239,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
* No new acks were receieved for data sent to this
|
||||
* dest. Therefore, according to the SFR algo for
|
||||
* CMT, no data sent to this dest can be marked for
|
||||
* FR using this SACK. (iyengar@cis.udel.edu,
|
||||
* 2005/05/12)
|
||||
* FR using this SACK.
|
||||
*/
|
||||
tp1 = TAILQ_NEXT(tp1, sctp_next);
|
||||
continue;
|
||||
@ -3298,11 +3289,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
* cumack earlier. If not already to be
|
||||
* rtx'd, If not a mixed sack and if tp1 is
|
||||
* not between two sacked TSNs, then mark by
|
||||
* one more.
|
||||
*/
|
||||
/*
|
||||
* Jana FIX, does this mean you strike it
|
||||
* twice (see code above?)
|
||||
* one more. NOTE that we are marking by one
|
||||
* additional time since the SACK DAC flag
|
||||
* indicates that two packets have been
|
||||
* received after this missing TSN.
|
||||
*/
|
||||
if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) &&
|
||||
compare_with_wrap(this_sack_lowest_newack, tp1->rec.data.TSN_seq, MAX_TSN)) {
|
||||
@ -3367,7 +3357,13 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
* If not a mixed sack and
|
||||
* if tp1 is not between two
|
||||
* sacked TSNs, then mark by
|
||||
* one more.
|
||||
* one more. NOTE that we
|
||||
* are marking by one
|
||||
* additional time since the
|
||||
* SACK DAC flag indicates
|
||||
* that two packets have
|
||||
* been received after this
|
||||
* missing TSN.
|
||||
*/
|
||||
if ((tp1->sent < SCTP_DATAGRAM_RESEND) &&
|
||||
(num_dests_sacked == 1) &&
|
||||
@ -3418,7 +3414,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
* cumack earlier. If not already to be
|
||||
* rtx'd, If not a mixed sack and if tp1 is
|
||||
* not between two sacked TSNs, then mark by
|
||||
* one more.
|
||||
* one more. NOTE that we are marking by one
|
||||
* additional time since the SACK DAC flag
|
||||
* indicates that two packets have been
|
||||
* received after this missing TSN.
|
||||
*/
|
||||
if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) &&
|
||||
compare_with_wrap(this_sack_lowest_newack, tp1->rec.data.TSN_seq, MAX_TSN)) {
|
||||
@ -3521,17 +3520,14 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
}
|
||||
/* fix counts and things */
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) stcb,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
tp1->whoTo->net_ack++;
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size)
|
||||
tp1->whoTo->flight_size -= tp1->book_size;
|
||||
else
|
||||
tp1->whoTo->flight_size = 0;
|
||||
sctp_flight_size_decrease(tp1);
|
||||
|
||||
#ifdef SCTP_LOG_RWND
|
||||
sctp_log_rwnd(SCTP_INCREASE_PEER_RWND,
|
||||
@ -3541,16 +3537,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
|
||||
asoc->peers_rwnd += (tp1->send_size + sctp_peer_chunk_oh);
|
||||
|
||||
/* remove from the total flight */
|
||||
if (asoc->total_flight >= tp1->book_size) {
|
||||
asoc->total_flight -= tp1->book_size;
|
||||
if (asoc->total_flight_count > 0)
|
||||
asoc->total_flight_count--;
|
||||
} else {
|
||||
asoc->total_flight = 0;
|
||||
asoc->total_flight_count = 0;
|
||||
}
|
||||
|
||||
|
||||
sctp_total_flight_decrease(stcb, tp1);
|
||||
if (alt != tp1->whoTo) {
|
||||
/* yes, there is an alternate. */
|
||||
sctp_free_remote_addr(tp1->whoTo);
|
||||
@ -3950,7 +3937,7 @@ sctp_cwnd_update(struct sctp_tcb *stcb,
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (asoc->fast_retran_loss_recovery && will_exit == 0) {
|
||||
if (asoc->fast_retran_loss_recovery && will_exit == 0 && sctp_cmt_on_off == 0) {
|
||||
/*
|
||||
* If we are in loss recovery we skip any cwnd
|
||||
* update
|
||||
@ -4071,45 +4058,12 @@ sctp_cwnd_update(struct sctp_tcb *stcb,
|
||||
}
|
||||
}
|
||||
|
||||
static int sctp_anal_print = 0;
|
||||
|
||||
static void
|
||||
sctp_print_fs_audit(struct sctp_association *asoc)
|
||||
sctp_fs_audit(struct sctp_association *asoc)
|
||||
{
|
||||
int cnt, i;
|
||||
struct sctp_tmit_chunk *chk;
|
||||
int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0;
|
||||
|
||||
printf("sdqc:%d stqc:%d retran:%d reasm:%d cnt:%d tot_flight:%d tfc:%d\n",
|
||||
(int)asoc->send_queue_cnt,
|
||||
(int)asoc->sent_queue_cnt,
|
||||
(int)asoc->sent_queue_retran_cnt,
|
||||
(int)asoc->size_on_reasm_queue,
|
||||
(int)asoc->cnt_on_reasm_queue,
|
||||
(int)asoc->total_flight,
|
||||
(int)asoc->total_flight_count);
|
||||
printf("my_rwnd:%d peers_rwnd:%d asoc calc cumack:%x\n",
|
||||
(int)asoc->my_rwnd, (int)asoc->peers_rwnd, asoc->last_acked_seq);
|
||||
for (i = 0; i < asoc->streamoutcnt; i++) {
|
||||
struct sctp_stream_queue_pending *sp;
|
||||
|
||||
cnt = 0;
|
||||
TAILQ_FOREACH(sp, &asoc->strmout[i].outqueue, next)
|
||||
cnt++;
|
||||
if (cnt) {
|
||||
printf("Stream %d has %d msgs yet to be sent in strm queue\n", i, cnt);
|
||||
}
|
||||
}
|
||||
cnt = 0;
|
||||
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
|
||||
cnt++;
|
||||
}
|
||||
printf("The control_send_queue has %d pending\n", cnt);
|
||||
cnt = 0;
|
||||
TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
|
||||
cnt++;
|
||||
}
|
||||
printf("The send_queue (waiting to get in flight) has %d chunks pending\n", cnt);
|
||||
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
|
||||
if (chk->sent < SCTP_DATAGRAM_RESEND) {
|
||||
inflight++;
|
||||
@ -4121,14 +4075,58 @@ sctp_print_fs_audit(struct sctp_association *asoc)
|
||||
above++;
|
||||
} else {
|
||||
acked++;
|
||||
printf("chk->sent:%x chk->tsn:%x\n",
|
||||
chk->sent, chk->rec.data.TSN_seq);
|
||||
}
|
||||
}
|
||||
printf("The sent_queue stats inflight:%d resend:%d acked:%d above:%d inbetween:%d\n",
|
||||
inflight, resend, acked, above, inbetween);
|
||||
if ((inflight > 0) || (inbetween > 0)) {
|
||||
panic("Flight size-express incorrect? \n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sctp_window_probe_recovery(struct sctp_tcb *stcb,
|
||||
struct sctp_association *asoc,
|
||||
struct sctp_nets *net,
|
||||
struct sctp_tmit_chunk *tp1)
|
||||
{
|
||||
struct sctp_tmit_chunk *chk;
|
||||
|
||||
/* First setup this one and get it moved back */
|
||||
tp1->sent = SCTP_DATAGRAM_UNSENT;
|
||||
tp1->window_probe = 0;
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
sctp_flight_size_decrease(tp1);
|
||||
sctp_total_flight_decrease(stcb, tp1);
|
||||
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
|
||||
TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next);
|
||||
asoc->sent_queue_cnt--;
|
||||
asoc->send_queue_cnt++;
|
||||
/*
|
||||
* Now all guys marked for RESEND on the sent_queue must be moved
|
||||
* back too.
|
||||
*/
|
||||
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
|
||||
if (chk->sent == SCTP_DATAGRAM_RESEND) {
|
||||
/* Another chunk to move */
|
||||
chk->sent = SCTP_DATAGRAM_UNSENT;
|
||||
chk->window_probe = 0;
|
||||
/* It should not be in flight */
|
||||
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
|
||||
TAILQ_INSERT_AFTER(&asoc->send_queue, tp1, chk, sctp_next);
|
||||
asoc->sent_queue_cnt--;
|
||||
asoc->send_queue_cnt++;
|
||||
sctp_ucount_decr(asoc->sent_queue_retran_cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
uint32_t rwnd, int nonce_sum_flag, int *abort_now)
|
||||
@ -4138,6 +4136,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
struct sctp_tmit_chunk *tp1, *tp2;
|
||||
uint32_t old_rwnd;
|
||||
int win_probe_recovery = 0;
|
||||
int win_probe_recovered = 0;
|
||||
int j, done_once;;
|
||||
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
@ -4162,19 +4161,22 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
if (sctp_strict_sacks) {
|
||||
uint32_t send_s;
|
||||
|
||||
if (TAILQ_EMPTY(&asoc->send_queue)) {
|
||||
send_s = asoc->sending_seq;
|
||||
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
|
||||
tp1 = TAILQ_LAST(&asoc->sent_queue,
|
||||
sctpchunk_listhead);
|
||||
send_s = tp1->rec.data.TSN_seq + 1;
|
||||
} else {
|
||||
tp1 = TAILQ_FIRST(&asoc->send_queue);
|
||||
send_s = tp1->rec.data.TSN_seq;
|
||||
send_s = asoc->sending_seq;
|
||||
}
|
||||
if ((cumack == send_s) ||
|
||||
compare_with_wrap(cumack, send_s, MAX_TSN)) {
|
||||
#ifdef INVARIANTS /* for testing only */
|
||||
panic("Impossible sack 1");
|
||||
#else
|
||||
#ifndef INVARIANTS
|
||||
struct mbuf *oper;
|
||||
|
||||
#endif
|
||||
#ifdef INVARIANTS
|
||||
panic("Impossible sack 1");
|
||||
#else
|
||||
*abort_now = 1;
|
||||
/* XXX */
|
||||
oper = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) + sizeof(uint32_t)),
|
||||
@ -4221,27 +4223,17 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
* flight. Higher values may
|
||||
* occur during marking
|
||||
*/
|
||||
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) stcb,
|
||||
tp1->rec.data.TSN_seq);
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size) {
|
||||
tp1->whoTo->flight_size -= tp1->book_size;
|
||||
} else {
|
||||
tp1->whoTo->flight_size = 0;
|
||||
}
|
||||
|
||||
if (asoc->total_flight >= tp1->book_size) {
|
||||
asoc->total_flight -= tp1->book_size;
|
||||
if (asoc->total_flight_count > 0)
|
||||
asoc->total_flight_count--;
|
||||
} else {
|
||||
asoc->total_flight = 0;
|
||||
asoc->total_flight_count = 0;
|
||||
sctp_flight_size_decrease(tp1);
|
||||
sctp_total_flight_decrease(stcb, tp1);
|
||||
}
|
||||
tp1->whoTo->net_ack += tp1->send_size;
|
||||
if (tp1->snd_count < 2) {
|
||||
@ -4414,6 +4406,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
if (win_probe_recovery && (net->window_probe)) {
|
||||
net->window_probe = 0;
|
||||
win_probe_recovered = 1;
|
||||
/*
|
||||
* Find first chunk that was used with window probe
|
||||
* and clear the sent
|
||||
@ -4421,15 +4414,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
|
||||
if (tp1->window_probe) {
|
||||
/* move back to data send queue */
|
||||
tp1->sent = SCTP_DATAGRAM_UNSENT;
|
||||
tp1->window_probe = 0;
|
||||
net->flight_size -= tp1->book_size;
|
||||
asoc->total_flight -= tp1->book_size;
|
||||
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
|
||||
TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next);
|
||||
asoc->sent_queue_cnt--;
|
||||
asoc->send_queue_cnt++;
|
||||
asoc->total_flight_count--;
|
||||
sctp_window_probe_recovery(stcb, asoc, net, tp1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -4463,12 +4448,10 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
if ((j == 0) &&
|
||||
(!TAILQ_EMPTY(&asoc->sent_queue)) &&
|
||||
(asoc->sent_queue_retran_cnt == 0) &&
|
||||
(win_probe_recovered == 0) &&
|
||||
(done_once == 0)) {
|
||||
/* huh, this should not happen */
|
||||
if (sctp_anal_print == 0) {
|
||||
printf("Flight size-express incorrect? cumack:%x\n", cumack);
|
||||
sctp_print_fs_audit(asoc);
|
||||
}
|
||||
sctp_fs_audit(asoc);
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
net->flight_size = 0;
|
||||
}
|
||||
@ -4477,18 +4460,12 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
|
||||
asoc->sent_queue_retran_cnt = 0;
|
||||
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
|
||||
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
|
||||
tp1->whoTo->flight_size += tp1->book_size;
|
||||
asoc->total_flight += tp1->book_size;
|
||||
asoc->total_flight_count++;
|
||||
sctp_flight_size_increase(tp1);
|
||||
sctp_total_flight_increase(stcb, tp1);
|
||||
} else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
|
||||
asoc->sent_queue_retran_cnt++;
|
||||
}
|
||||
}
|
||||
if (sctp_anal_print == 0) {
|
||||
printf("After audit, totalflight:%d, retran_cnt:%d\n",
|
||||
asoc->total_flight, asoc->sent_queue_retran_cnt);
|
||||
sctp_anal_print = 1;
|
||||
}
|
||||
done_once = 1;
|
||||
goto again;
|
||||
}
|
||||
@ -4597,12 +4574,13 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
uint16_t num_seg, num_dup;
|
||||
uint16_t wake_him = 0;
|
||||
unsigned int sack_length;
|
||||
uint32_t send_s;
|
||||
uint32_t send_s = 0;
|
||||
long j;
|
||||
int accum_moved = 0;
|
||||
int will_exit_fast_recovery = 0;
|
||||
uint32_t a_rwnd, old_rwnd;
|
||||
int win_probe_recovery = 0;
|
||||
int win_probe_recovered = 0;
|
||||
struct sctp_nets *net = NULL;
|
||||
int nonce_sum_flag, ecn_seg_sums = 0;
|
||||
int done_once;
|
||||
@ -4685,22 +4663,26 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* reality check */
|
||||
if (TAILQ_EMPTY(&asoc->send_queue)) {
|
||||
send_s = asoc->sending_seq;
|
||||
} else {
|
||||
tp1 = TAILQ_FIRST(&asoc->send_queue);
|
||||
send_s = tp1->rec.data.TSN_seq;
|
||||
}
|
||||
|
||||
if (sctp_strict_sacks) {
|
||||
/* reality check */
|
||||
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
|
||||
tp1 = TAILQ_LAST(&asoc->sent_queue,
|
||||
sctpchunk_listhead);
|
||||
send_s = tp1->rec.data.TSN_seq + 1;
|
||||
} else {
|
||||
send_s = asoc->sending_seq;
|
||||
}
|
||||
if (cum_ack == send_s ||
|
||||
compare_with_wrap(cum_ack, send_s, MAX_TSN)) {
|
||||
#ifdef INVARIANTS /* for testing only */
|
||||
#ifndef INVARIANTS
|
||||
struct mbuf *oper;
|
||||
|
||||
#endif
|
||||
#ifdef INVARIANTS
|
||||
hopeless_peer:
|
||||
panic("Impossible sack 1");
|
||||
#else
|
||||
struct mbuf *oper;
|
||||
|
||||
|
||||
/*
|
||||
* no way, we have not even sent this TSN out yet.
|
||||
@ -4826,25 +4808,16 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
tp1->whoTo->dest_state &=
|
||||
~SCTP_ADDR_UNCONFIRMED;
|
||||
}
|
||||
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) stcb,
|
||||
tp1->rec.data.TSN_seq);
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size) {
|
||||
tp1->whoTo->flight_size -= tp1->book_size;
|
||||
} else {
|
||||
tp1->whoTo->flight_size = 0;
|
||||
}
|
||||
if (asoc->total_flight >= tp1->book_size) {
|
||||
asoc->total_flight -= tp1->book_size;
|
||||
if (asoc->total_flight_count > 0)
|
||||
asoc->total_flight_count--;
|
||||
} else {
|
||||
asoc->total_flight = 0;
|
||||
asoc->total_flight_count = 0;
|
||||
sctp_flight_size_decrease(tp1);
|
||||
sctp_total_flight_decrease(stcb, tp1);
|
||||
}
|
||||
tp1->whoTo->net_ack += tp1->send_size;
|
||||
|
||||
@ -5013,8 +4986,11 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
}
|
||||
if ((TAILQ_FIRST(&asoc->sent_queue) == NULL) &&
|
||||
(asoc->total_flight > 0)) {
|
||||
printf("Warning flight size incorrect should be 0 is %d\n",
|
||||
asoc->total_flight);
|
||||
panic("Warning flight size is postive and should be 0");
|
||||
/*
|
||||
printf("Warning flight size incorrect should be 0 is %d\n",
|
||||
asoc->total_flight);
|
||||
*/
|
||||
asoc->total_flight = 0;
|
||||
}
|
||||
if (tp1->data) {
|
||||
@ -5073,7 +5049,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
*/
|
||||
|
||||
if (num_seg)
|
||||
sctp_check_for_revoked(asoc, cum_ack, biggest_tsn_acked);
|
||||
sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked);
|
||||
else if (asoc->saw_sack_with_frags) {
|
||||
int cnt_revoked = 0;
|
||||
|
||||
@ -5084,8 +5060,16 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
if ((tp1->sent > SCTP_DATAGRAM_RESEND) &&
|
||||
(tp1->sent < SCTP_FORWARD_TSN_SKIP)) {
|
||||
tp1->sent = SCTP_DATAGRAM_SENT;
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) tp1->whoTo,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
sctp_flight_size_increase(tp1);
|
||||
sctp_total_flight_increase(stcb, tp1);
|
||||
tp1->rec.data.chunk_was_revoked = 1;
|
||||
tp1->whoTo->flight_size += tp1->book_size;
|
||||
/*
|
||||
* To ensure that this increase in
|
||||
* flightsize, which is artificial,
|
||||
@ -5094,8 +5078,6 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
* artificially.
|
||||
*/
|
||||
tp1->whoTo->cwnd += tp1->book_size;
|
||||
asoc->total_flight_count++;
|
||||
asoc->total_flight += tp1->book_size;
|
||||
cnt_revoked++;
|
||||
}
|
||||
}
|
||||
@ -5282,12 +5264,10 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
}
|
||||
/*
|
||||
* CMT fast recovery code. Need to debug. ((sctp_cmt_on_off == 1) &&
|
||||
* (net->fast_retran_loss_recovery == 0))) if
|
||||
* ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off ==
|
||||
* 1)) {
|
||||
* (net->fast_retran_loss_recovery == 0)))
|
||||
*/
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
if (asoc->fast_retran_loss_recovery == 0) {
|
||||
if ((asoc->fast_retran_loss_recovery == 0) || (sctp_cmt_on_off == 1)) {
|
||||
/* out of a RFC2582 Fast recovery window? */
|
||||
if (net->net_ack > 0) {
|
||||
/*
|
||||
@ -5467,6 +5447,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
if (win_probe_recovery && (net->window_probe)) {
|
||||
net->window_probe = 0;
|
||||
win_probe_recovered = 1;
|
||||
/*-
|
||||
* Find first chunk that was used with
|
||||
* window probe and clear the event. Put
|
||||
@ -5475,15 +5456,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
*/
|
||||
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
|
||||
if (tp1->window_probe) {
|
||||
tp1->sent = SCTP_DATAGRAM_UNSENT;
|
||||
tp1->window_probe = 0;
|
||||
net->flight_size -= tp1->book_size;
|
||||
asoc->total_flight -= tp1->book_size;
|
||||
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
|
||||
TAILQ_INSERT_HEAD(&asoc->send_queue, tp1, sctp_next);
|
||||
asoc->sent_queue_cnt--;
|
||||
asoc->send_queue_cnt++;
|
||||
asoc->total_flight_count--;
|
||||
sctp_window_probe_recovery(stcb, asoc, net, tp1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -5492,18 +5465,28 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
j++;
|
||||
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
|
||||
stcb->sctp_ep, stcb, net);
|
||||
} else {
|
||||
if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
|
||||
stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
|
||||
}
|
||||
if (sctp_early_fr) {
|
||||
if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
|
||||
SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
|
||||
SCTP_FROM_SCTP_INDATA + SCTP_LOC_23);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((j == 0) &&
|
||||
(!TAILQ_EMPTY(&asoc->sent_queue)) &&
|
||||
(asoc->sent_queue_retran_cnt == 0) &&
|
||||
(win_probe_recovered == 0) &&
|
||||
(done_once == 0)) {
|
||||
/* huh, this should not happen */
|
||||
if (sctp_anal_print == 0) {
|
||||
printf("Flight size incorrect sack-cumack:%x prev_last_ack:%x? fixing??",
|
||||
cum_ack, sav_cum_ack);
|
||||
sctp_print_fs_audit(asoc);
|
||||
}
|
||||
sctp_fs_audit(asoc);
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
net->flight_size = 0;
|
||||
}
|
||||
@ -5512,18 +5495,12 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
|
||||
asoc->sent_queue_retran_cnt = 0;
|
||||
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
|
||||
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
|
||||
tp1->whoTo->flight_size += tp1->book_size;
|
||||
asoc->total_flight += tp1->book_size;
|
||||
asoc->total_flight_count++;
|
||||
sctp_flight_size_increase(tp1);
|
||||
sctp_total_flight_increase(stcb, tp1);
|
||||
} else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
|
||||
asoc->sent_queue_retran_cnt++;
|
||||
}
|
||||
}
|
||||
if (sctp_anal_print == 0) {
|
||||
printf("After audit, totalflight:%d retran count:%d\n",
|
||||
asoc->total_flight, asoc->sent_queue_retran_cnt);
|
||||
sctp_anal_print = 1;
|
||||
}
|
||||
done_once = 1;
|
||||
goto again;
|
||||
}
|
||||
|
@ -2616,26 +2616,14 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
|
||||
|
||||
/* fix counts and things */
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP,
|
||||
tp1->whoTo->flight_size,
|
||||
tp1->book_size,
|
||||
(uintptr_t) stcb,
|
||||
tp1->rec.data.TSN_seq);
|
||||
#endif
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size)
|
||||
tp1->whoTo->flight_size -= tp1->book_size;
|
||||
else
|
||||
tp1->whoTo->flight_size = 0;
|
||||
|
||||
if (stcb->asoc.total_flight >= tp1->book_size) {
|
||||
stcb->asoc.total_flight -= tp1->book_size;
|
||||
if (stcb->asoc.total_flight_count > 0)
|
||||
stcb->asoc.total_flight_count--;
|
||||
} else {
|
||||
stcb->asoc.total_flight = 0;
|
||||
stcb->asoc.total_flight_count = 0;
|
||||
}
|
||||
tp1->snd_count--;
|
||||
sctp_flight_size_decrease(tp1);
|
||||
sctp_total_flight_decrease(stcb, tp1);
|
||||
} {
|
||||
/* audit code */
|
||||
unsigned int audit;
|
||||
@ -4883,8 +4871,6 @@ sctp_input(i_pak, off)
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* common chunk processing
|
||||
*/
|
||||
|
@ -2150,21 +2150,18 @@ sctp_add_addresses_to_i_ia(struct sctp_inpcb *inp, struct sctp_scoping *scope,
|
||||
}
|
||||
|
||||
static struct sctp_ifa *
|
||||
sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa,
|
||||
sctp_is_ifa_addr_preferred(struct sctp_ifa *ifa,
|
||||
uint8_t dest_is_loop,
|
||||
uint8_t dest_is_priv,
|
||||
sa_family_t fam)
|
||||
{
|
||||
uint8_t dest_is_global = 0;
|
||||
|
||||
/*
|
||||
* is_scope -> dest_is_priv is true if destination is a private
|
||||
* address
|
||||
*/
|
||||
/* dest_is_priv is true if destination is a private address */
|
||||
/* dest_is_loop is true if destination is a loopback addresses */
|
||||
|
||||
/*
|
||||
* Here we determine if its a prefered address. A prefered address
|
||||
* Here we determine if its a preferred address. A preferred address
|
||||
* means it is the same scope or higher scope then the destination.
|
||||
* L = loopback, P = private, G = global
|
||||
* ----------------------------------------- src | dest | result
|
||||
@ -2189,7 +2186,7 @@ sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa,
|
||||
}
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) {
|
||||
printf("Is destination prefered:");
|
||||
printf("Is destination preferred:");
|
||||
sctp_print_address(&ifa->address.sa);
|
||||
}
|
||||
#endif
|
||||
@ -2280,7 +2277,7 @@ sctp_is_ifa_addr_prefered(struct sctp_ifa *ifa,
|
||||
printf("YES\n");
|
||||
}
|
||||
#endif
|
||||
/* its a prefered address */
|
||||
/* its a preferred address */
|
||||
return (ifa);
|
||||
}
|
||||
|
||||
@ -2334,15 +2331,14 @@ sctp_is_ifa_addr_acceptable(struct sctp_ifa *ifa,
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now that we know what is what, implement or table this could in
|
||||
* Now that we know what is what, implement our table. This could in
|
||||
* theory be done slicker (it used to be), but this is
|
||||
* straightforward and easier to validate :-)
|
||||
*/
|
||||
|
||||
if ((ifa->src_is_loop == 0) && (dest_is_priv)) {
|
||||
if ((ifa->src_is_loop == 1) && (dest_is_priv)) {
|
||||
return (NULL);
|
||||
}
|
||||
if ((ifa->src_is_loop == 0) && (dest_is_global)) {
|
||||
if ((ifa->src_is_loop == 1) && (dest_is_global)) {
|
||||
return (NULL);
|
||||
}
|
||||
/* its an acceptable address */
|
||||
@ -2427,15 +2423,15 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
|
||||
sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index);
|
||||
/*
|
||||
* first question, is the ifn we will emit on in our list, if so, we
|
||||
* want such an address. Note that we first looked for a prefered
|
||||
* want such an address. Note that we first looked for a preferred
|
||||
* address.
|
||||
*/
|
||||
if (sctp_ifn) {
|
||||
/* is a prefered one on the interface we route out? */
|
||||
/* is a preferred one on the interface we route out? */
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
sifa = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_preferred(sctp_ifa, dest_is_loop, dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
if (sctp_is_addr_in_ep(inp, sifa)) {
|
||||
@ -2446,9 +2442,9 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
|
||||
}
|
||||
/*
|
||||
* ok, now we now need to find one on the list of the addresses. We
|
||||
* can't get one on the emitting interface so lets find first a
|
||||
* prefered one. If not that a acceptable one otherwise... we return
|
||||
* NULL.
|
||||
* can't get one on the emitting interface so let's find first a
|
||||
* preferred one. If not that an acceptable one otherwise... we
|
||||
* return NULL.
|
||||
*/
|
||||
starting_point = inp->next_addr_touse;
|
||||
once_again:
|
||||
@ -2461,7 +2457,7 @@ sctp_choose_boundspecific_inp(struct sctp_inpcb *inp,
|
||||
/* address has been removed */
|
||||
continue;
|
||||
}
|
||||
sifa = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_preferred(laddr->ifa, dest_is_loop, dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
atomic_add_int(&sifa->refcount, 1);
|
||||
@ -2535,17 +2531,17 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
sctp_ifn = sctp_find_ifn(vrf, ifn, ifn_index);
|
||||
|
||||
/*
|
||||
* first question, is the ifn we will emit on in our list, if so, we
|
||||
* want that one.. First we look for a prefered. Second we go for an
|
||||
* acceptable.
|
||||
* first question, is the ifn we will emit on in our list? If so,
|
||||
* we want that one. First we look for a preferred. Second, we go
|
||||
* for an acceptable.
|
||||
*/
|
||||
if (sctp_ifn) {
|
||||
/* first try for a prefered address on the ep */
|
||||
/* first try for a preferred address on the ep */
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
if (sctp_is_addr_in_ep(inp, sctp_ifa)) {
|
||||
sifa = sctp_is_ifa_addr_prefered(sctp_ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_preferred(sctp_ifa, dest_is_loop, dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
if ((non_asoc_addr_ok == 0) &&
|
||||
@ -2578,7 +2574,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
}
|
||||
/*
|
||||
* if we can't find one like that then we must look at all addresses
|
||||
* bound to pick one at first prefereable then secondly acceptable.
|
||||
* bound to pick one at first preferable then secondly acceptable.
|
||||
*/
|
||||
starting_point = stcb->asoc.last_used_address;
|
||||
sctp_from_the_top:
|
||||
@ -2593,7 +2589,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
/* address has been removed */
|
||||
continue;
|
||||
}
|
||||
sifa = sctp_is_ifa_addr_prefered(laddr->ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_preferred(laddr->ifa, dest_is_loop, dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
if ((non_asoc_addr_ok == 0) &&
|
||||
@ -2645,7 +2641,7 @@ sctp_choose_boundspecific_stcb(struct sctp_inpcb *inp,
|
||||
}
|
||||
|
||||
static struct sctp_ifa *
|
||||
sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
sctp_select_nth_preferred_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
struct sctp_tcb *stcb,
|
||||
int non_asoc_addr_ok,
|
||||
uint8_t dest_is_loop,
|
||||
@ -2659,7 +2655,7 @@ sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
LIST_FOREACH(ifa, &ifn->ifalist, next_ifa) {
|
||||
if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
sifa = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_preferred(ifa, dest_is_loop, dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
if (stcb) {
|
||||
@ -2681,7 +2677,7 @@ sctp_select_nth_prefered_addr_from_ifn_boundall(struct sctp_ifn *ifn,
|
||||
|
||||
|
||||
static int
|
||||
sctp_count_num_prefered_boundall(struct sctp_ifn *ifn,
|
||||
sctp_count_num_preferred_boundall(struct sctp_ifn *ifn,
|
||||
struct sctp_tcb *stcb,
|
||||
int non_asoc_addr_ok,
|
||||
uint8_t dest_is_loop,
|
||||
@ -2695,7 +2691,7 @@ sctp_count_num_prefered_boundall(struct sctp_ifn *ifn,
|
||||
if ((ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0)) {
|
||||
continue;
|
||||
}
|
||||
sifa = sctp_is_ifa_addr_prefered(ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_preferred(ifa, dest_is_loop, dest_is_priv, fam);
|
||||
if (sifa == NULL) {
|
||||
continue;
|
||||
}
|
||||
@ -2724,7 +2720,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
int non_asoc_addr_ok,
|
||||
sa_family_t fam)
|
||||
{
|
||||
int cur_addr_num = 0, num_prefered = 0;
|
||||
int cur_addr_num = 0, num_preferred = 0;
|
||||
void *ifn;
|
||||
struct sctp_ifn *sctp_ifn, *looked_at = NULL, *emit_ifn;
|
||||
struct sctp_ifa *sctp_ifa, *sifa;
|
||||
@ -2732,10 +2728,10 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
struct sctp_vrf *vrf;
|
||||
|
||||
/*
|
||||
* For boundall we can use any address in the association. If
|
||||
* For boundall we can use any address in the association. If
|
||||
* non_asoc_addr_ok is set we can use any address (at least in
|
||||
* theory). So we look for prefered addresses first. If we find one,
|
||||
* we use it. Otherwise we next try to get an address on the
|
||||
* theory). So we look for preferred addresses first. If we find
|
||||
* one, we use it. Otherwise we next try to get an address on the
|
||||
* interface, which we should be able to do (unless non_asoc_addr_ok
|
||||
* is false and we are routed out that way). In these cases where we
|
||||
* can't use the address of the interface we go through all the
|
||||
@ -2760,17 +2756,17 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
if (net) {
|
||||
cur_addr_num = net->indx_of_eligible_next_to_use;
|
||||
}
|
||||
num_prefered = sctp_count_num_prefered_boundall(sctp_ifn,
|
||||
num_preferred = sctp_count_num_preferred_boundall(sctp_ifn,
|
||||
stcb,
|
||||
non_asoc_addr_ok,
|
||||
dest_is_loop,
|
||||
dest_is_priv, fam);
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) {
|
||||
printf("Found %d prefered source addresses\n", num_prefered);
|
||||
printf("Found %d preferred source addresses\n", num_preferred);
|
||||
}
|
||||
#endif
|
||||
if (num_prefered == 0) {
|
||||
if (num_preferred == 0) {
|
||||
/*
|
||||
* no eligible addresses, we must use some other interface
|
||||
* address if we can find one.
|
||||
@ -2782,7 +2778,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
* may vary from call to call due to addresses being deprecated
|
||||
* etc..
|
||||
*/
|
||||
if (cur_addr_num >= num_prefered) {
|
||||
if (cur_addr_num >= num_preferred) {
|
||||
cur_addr_num = 0;
|
||||
}
|
||||
/*
|
||||
@ -2794,7 +2790,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
printf("cur_addr_num:%d\n", cur_addr_num);
|
||||
}
|
||||
#endif
|
||||
sctp_ifa = sctp_select_nth_prefered_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
sctp_ifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
dest_is_priv, cur_addr_num, fam);
|
||||
|
||||
/* if sctp_ifa is NULL something changed??, fall to plan b. */
|
||||
@ -2807,8 +2803,8 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
return (sctp_ifa);
|
||||
}
|
||||
/*
|
||||
* plan_b: Look at all interfaces and find a prefered address. If no
|
||||
* prefered fall through to plan_c.
|
||||
* plan_b: Look at all interfaces and find a preferred address. If
|
||||
* no preferred fall through to plan_c.
|
||||
*/
|
||||
bound_all_plan_b:
|
||||
#ifdef SCTP_DEBUG
|
||||
@ -2824,14 +2820,14 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
if ((sctp_ifn == looked_at) && looked_at)
|
||||
/* already looked at this guy */
|
||||
continue;
|
||||
num_prefered = sctp_count_num_prefered_boundall(sctp_ifn, stcb, non_asoc_addr_ok,
|
||||
num_preferred = sctp_count_num_preferred_boundall(sctp_ifn, stcb, non_asoc_addr_ok,
|
||||
dest_is_loop, dest_is_priv, fam);
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) {
|
||||
printf("Found ifn:%p %d prefered source addresses\n", ifn, num_prefered);
|
||||
printf("Found ifn:%p %d preferred source addresses\n", ifn, num_preferred);
|
||||
}
|
||||
#endif
|
||||
if (num_prefered == 0) {
|
||||
if (num_preferred == 0) {
|
||||
/*
|
||||
* None on this interface.
|
||||
*/
|
||||
@ -2839,8 +2835,8 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
}
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) {
|
||||
printf("num prefered:%d on interface:%p cur_addr_num:%d\n",
|
||||
num_prefered,
|
||||
printf("num preferred:%d on interface:%p cur_addr_num:%d\n",
|
||||
num_preferred,
|
||||
sctp_ifn,
|
||||
cur_addr_num);
|
||||
}
|
||||
@ -2851,10 +2847,10 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
* use, this may vary from call to call due to addresses
|
||||
* being deprecated etc..
|
||||
*/
|
||||
if (cur_addr_num >= num_prefered) {
|
||||
if (cur_addr_num >= num_preferred) {
|
||||
cur_addr_num = 0;
|
||||
}
|
||||
sifa = sctp_select_nth_prefered_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
sifa = sctp_select_nth_preferred_addr_from_ifn_boundall(sctp_ifn, stcb, non_asoc_addr_ok, dest_is_loop,
|
||||
dest_is_priv, cur_addr_num, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
@ -2881,18 +2877,21 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
*/
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_OUTPUT2) {
|
||||
printf("Plan C no prefered for Dest, acceptable for?\n");
|
||||
printf("Plan C no preferred for Dest, acceptable for?\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
LIST_FOREACH(sctp_ifa, &emit_ifn->ifalist, next_ifa) {
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop,
|
||||
dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
if (stcb) {
|
||||
if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) {
|
||||
if ((non_asoc_addr_ok == 0) &&
|
||||
sctp_is_addr_restricted(stcb, sifa)) {
|
||||
/*
|
||||
* It is restricted for some reason..
|
||||
* probably not yet added.
|
||||
@ -2905,7 +2904,7 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
}
|
||||
|
||||
/*
|
||||
* plan_d: We are in trouble. No prefered address on the emit
|
||||
* plan_d: We are in trouble. No preferred address on the emit
|
||||
* interface. And not even a perfered address on all interfaces. Go
|
||||
* out and see if we can find an acceptable address somewhere
|
||||
* amongst all interfaces.
|
||||
@ -2925,13 +2924,17 @@ sctp_choose_boundall(struct sctp_inpcb *inp,
|
||||
continue;
|
||||
|
||||
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) && (non_asoc_addr_ok == 0))
|
||||
if ((sctp_ifa->localifa_flags & SCTP_ADDR_DEFER_USE) &&
|
||||
(non_asoc_addr_ok == 0))
|
||||
continue;
|
||||
sifa = sctp_is_ifa_addr_acceptable(sctp_ifa, dest_is_loop, dest_is_priv, fam);
|
||||
sifa = sctp_is_ifa_addr_acceptable(sctp_ifa,
|
||||
dest_is_loop,
|
||||
dest_is_priv, fam);
|
||||
if (sifa == NULL)
|
||||
continue;
|
||||
if (stcb) {
|
||||
if ((non_asoc_addr_ok == 0) && sctp_is_addr_restricted(stcb, sifa)) {
|
||||
if ((non_asoc_addr_ok == 0) &&
|
||||
sctp_is_addr_restricted(stcb, sifa)) {
|
||||
/*
|
||||
* It is restricted for some
|
||||
* reason.. probably not yet added.
|
||||
@ -3019,12 +3022,10 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
|
||||
* use the same concept but instead only consider the bound
|
||||
* addresses. If the bound set is NOT assigned to the interface then
|
||||
* we must use rotation amongst the bound addresses..
|
||||
*
|
||||
*/
|
||||
if (ro->ro_rt == NULL) {
|
||||
/*
|
||||
* Need a route to cache.
|
||||
*
|
||||
*/
|
||||
rtalloc_ign(ro, 0UL);
|
||||
did_rtalloc = 1;
|
||||
@ -3380,13 +3381,13 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
{
|
||||
/*
|
||||
* Given a mbuf chain (via SCTP_BUF_NEXT()) that holds a packet
|
||||
* header WITH a SCTPHDR but no IP header, endpoint inp and sa
|
||||
* structure. - fill in the HMAC digest of any AUTH chunk in the
|
||||
* packet - calculate SCTP checksum and fill in - prepend a IP
|
||||
* address header - if boundall use INADDR_ANY - if boundspecific do
|
||||
* source address selection - set fragmentation option for ipV4 - On
|
||||
* return from IP output, check/adjust mtu size - of output
|
||||
* interface and smallest_mtu size as well.
|
||||
* header WITH an SCTPHDR but no IP header, endpoint inp and sa
|
||||
* structure: - fill in the HMAC digest of any AUTH chunk in the
|
||||
* packet. - calculate and fill in the SCTP checksum. - prepend an
|
||||
* IP address header. - if boundall use INADDR_ANY. - if
|
||||
* boundspecific do source address selection. - set fragmentation
|
||||
* option for ipV4. - On return from IP output, check/adjust mtu
|
||||
* size of output interface and smallest_mtu size as well.
|
||||
*/
|
||||
/* Will need ifdefs around this */
|
||||
struct mbuf *o_pak;
|
||||
@ -3882,7 +3883,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
void
|
||||
sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
|
||||
{
|
||||
struct mbuf *m, *m_at, *m_last;
|
||||
struct mbuf *m, *m_at, *mp_last;
|
||||
struct sctp_nets *net;
|
||||
struct sctp_init_msg *initm;
|
||||
struct sctp_supported_addr_param *sup_addr;
|
||||
@ -3896,7 +3897,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
|
||||
int p_len;
|
||||
|
||||
/* INIT's always go to the primary (and usually ONLY address) */
|
||||
m_last = NULL;
|
||||
mp_last = NULL;
|
||||
net = stcb->asoc.primary_destination;
|
||||
if (net == NULL) {
|
||||
net = TAILQ_FIRST(&stcb->asoc.nets);
|
||||
@ -4119,7 +4120,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
|
||||
p_len = 0;
|
||||
for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
|
||||
if (SCTP_BUF_NEXT(m_at) == NULL)
|
||||
m_last = m_at;
|
||||
mp_last = m_at;
|
||||
p_len += SCTP_BUF_LEN(m_at);
|
||||
}
|
||||
initm->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr)));
|
||||
@ -4130,15 +4131,15 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
|
||||
|
||||
/* I don't expect this to execute but we will be safe here */
|
||||
padval = p_len % 4;
|
||||
if ((padval) && (m_last)) {
|
||||
if ((padval) && (mp_last)) {
|
||||
/*
|
||||
* The compiler worries that m_last may not be set even
|
||||
* though I think it is impossible :-> however we add m_last
|
||||
* here just in case.
|
||||
* The compiler worries that mp_last may not be set even
|
||||
* though I think it is impossible :-> however we add
|
||||
* mp_last here just in case.
|
||||
*/
|
||||
int ret;
|
||||
|
||||
ret = sctp_add_pad_tombuf(m_last, (4 - padval));
|
||||
ret = sctp_add_pad_tombuf(mp_last, (4 - padval));
|
||||
if (ret) {
|
||||
/* Houston we have a problem, no space */
|
||||
sctp_m_freem(m);
|
||||
@ -4514,7 +4515,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
struct sctp_init_chunk *init_chk)
|
||||
{
|
||||
struct sctp_association *asoc;
|
||||
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *m_last;
|
||||
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
|
||||
struct sctp_init_msg *initackm_out;
|
||||
struct sctp_ecn_supported_param *ecn;
|
||||
struct sctp_prsctp_supported_param *prsctp;
|
||||
@ -4543,7 +4544,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
vrf_id = inp->def_vrf_id;
|
||||
asoc = NULL;
|
||||
}
|
||||
m_last = NULL;
|
||||
mp_last = NULL;
|
||||
if ((asoc != NULL) &&
|
||||
(SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
|
||||
(sctp_are_there_new_addresses(asoc, init_pkt, iphlen, offset))) {
|
||||
@ -5088,7 +5089,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
p_len += SCTP_BUF_LEN(m_tmp);
|
||||
if (SCTP_BUF_NEXT(m_tmp) == NULL) {
|
||||
/* m_tmp should now point to last one */
|
||||
m_last = m_tmp;
|
||||
mp_last = m_tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -5098,11 +5099,11 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
* here since the timer will drive a retranmission.
|
||||
*/
|
||||
padval = p_len % 4;
|
||||
if ((padval) && (m_last)) {
|
||||
/* see my previous comments on m_last */
|
||||
if ((padval) && (mp_last)) {
|
||||
/* see my previous comments on mp_last */
|
||||
int ret;
|
||||
|
||||
ret = sctp_add_pad_tombuf(m_last, (4 - padval));
|
||||
ret = sctp_add_pad_tombuf(mp_last, (4 - padval));
|
||||
if (ret) {
|
||||
/* Houston we have a problem, no space */
|
||||
sctp_m_freem(m);
|
||||
@ -6034,12 +6035,11 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb,
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
|
||||
data_list[i]->whoTo->flight_size,
|
||||
data_list[i]->book_size,
|
||||
(uintptr_t) stcb,
|
||||
(uintptr_t) data_list[i]->whoTo,
|
||||
data_list[i]->rec.data.TSN_seq);
|
||||
#endif
|
||||
net->flight_size += data_list[i]->book_size;
|
||||
asoc->total_flight += data_list[i]->book_size;
|
||||
asoc->total_flight_count++;
|
||||
sctp_flight_size_increase(data_list[i]);
|
||||
sctp_total_flight_increase(stcb, data_list[i]);
|
||||
#ifdef SCTP_LOG_RWND
|
||||
sctp_log_rwnd(SCTP_DECREASE_PEER_RWND,
|
||||
asoc->peers_rwnd, data_list[i]->send_size, sctp_peer_chunk_oh);
|
||||
@ -8250,7 +8250,6 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
|
||||
|
||||
|
||||
} else {
|
||||
sctp_ucount_incr(asoc->total_flight_count);
|
||||
#ifdef SCTP_LOG_RWND
|
||||
sctp_log_rwnd(SCTP_DECREASE_PEER_RWND,
|
||||
asoc->peers_rwnd, data_list[i]->send_size, sctp_peer_chunk_oh);
|
||||
@ -8260,14 +8259,14 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
|
||||
sctp_peer_chunk_oh));
|
||||
}
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_RSND,
|
||||
data_list[i]->whoTo->flight_size,
|
||||
data_list[i]->book_size,
|
||||
(uintptr_t) stcb,
|
||||
(uintptr_t) data_list[i]->whoTo,
|
||||
data_list[i]->rec.data.TSN_seq);
|
||||
#endif
|
||||
net->flight_size += data_list[i]->book_size;
|
||||
asoc->total_flight += data_list[i]->book_size;
|
||||
sctp_flight_size_increase(data_list[i]);
|
||||
sctp_total_flight_increase(stcb, data_list[i]);
|
||||
if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
|
||||
/* SWS sender side engages */
|
||||
asoc->peers_rwnd = 0;
|
||||
@ -8970,7 +8969,6 @@ sctp_send_sack(struct sctp_tcb *stcb)
|
||||
|
||||
gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk));
|
||||
|
||||
|
||||
siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
|
||||
if (asoc->cumulative_tsn < asoc->mapping_array_base_tsn) {
|
||||
offset = 1;
|
||||
@ -10309,8 +10307,6 @@ sctp_send_operr_to(struct mbuf *m, int iphlen,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct mbuf *
|
||||
sctp_copy_resume(struct sctp_stream_queue_pending *sp,
|
||||
struct uio *uio,
|
||||
@ -10321,6 +10317,22 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp,
|
||||
uint32_t * sndout,
|
||||
struct mbuf **new_tail)
|
||||
{
|
||||
|
||||
/*#if defined(__FreeBSD__) && __FreeBSD_version >= 602000*/
|
||||
#if defined(_NOT_YET_)
|
||||
|
||||
struct mbuf *m;
|
||||
|
||||
/* take out max_hdr */
|
||||
m = m_uiotombuf(uio, M_WAITOK, max_send_len, 0,
|
||||
(M_PKTHDR | (user_marks_eor ? M_EOR : 0)));
|
||||
if (m == NULL)
|
||||
*error = ENOMEM;
|
||||
else
|
||||
*sndout = m_length(m, NULL);
|
||||
*new_tail = m_last(m);
|
||||
return (m);
|
||||
#else
|
||||
int left, cancpy, willcpy;
|
||||
struct mbuf *m, *prev, *head;
|
||||
|
||||
@ -10368,6 +10380,7 @@ sctp_copy_resume(struct sctp_stream_queue_pending *sp,
|
||||
}
|
||||
}
|
||||
return (head);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -10375,7 +10388,19 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp,
|
||||
struct uio *uio,
|
||||
int resv_upfront)
|
||||
{
|
||||
int left, cancpy, willcpy, error;
|
||||
int left;
|
||||
|
||||
/*#if defined(__FreeBSD__) && __FreeBSD_version >= 602000*/
|
||||
#if defined(_NOT_YET_)
|
||||
left = sp->length;
|
||||
sp->data = m_uiotombuf(uio, M_WAITOK, 0, resv_upfront, M_PKTHDR);
|
||||
if (sp->data == NULL)
|
||||
return (ENOMEM);
|
||||
sp->length = m_length(sp->data, NULL);
|
||||
sp->tail_mbuf = m_last(sp->data);
|
||||
return (0);
|
||||
#else
|
||||
int cancpy, willcpy, error;
|
||||
struct mbuf *m, *head;
|
||||
int cpsz = 0;
|
||||
|
||||
@ -10423,6 +10448,7 @@ sctp_copy_one(struct sctp_stream_queue_pending *sp,
|
||||
sp->data = head;
|
||||
sp->length = cpsz;
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -476,7 +476,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
if (inp->def_vrf_id == vrf_id) {
|
||||
if (inp->def_vrf_id != vrf_id) {
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
continue;
|
||||
}
|
||||
@ -1143,7 +1143,7 @@ struct sctp_tcb *
|
||||
sctp_findassociation_addr_sa(struct sockaddr *to, struct sockaddr *from,
|
||||
struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool, uint32_t vrf_id)
|
||||
{
|
||||
struct sctp_inpcb *inp;
|
||||
struct sctp_inpcb *inp = NULL;
|
||||
struct sctp_tcb *retval;
|
||||
|
||||
SCTP_INP_INFO_RLOCK();
|
||||
@ -1954,7 +1954,7 @@ sctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id)
|
||||
} else {
|
||||
/* t_inp is bound only V4 */
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
|
||||
SCTP_IPV6_V6ONLY(t_inp)) {
|
||||
SCTP_IPV6_V6ONLY(inp)) {
|
||||
/* no conflict */
|
||||
continue;
|
||||
}
|
||||
@ -3549,17 +3549,33 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
/* now clean up any other timers */
|
||||
SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
|
||||
asoc->hb_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
|
||||
asoc->dack_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
|
||||
/*-
|
||||
* For stream reset we don't blast this unless
|
||||
* it is a str-reset timer, it might be the
|
||||
* free-asoc timer which we DON'T want to
|
||||
* disturb.
|
||||
*/
|
||||
if (asoc->strreset_timer.type == SCTP_TIMER_TYPE_STRRESET)
|
||||
asoc->strreset_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
|
||||
asoc->asconf_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
|
||||
asoc->autoclose_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer);
|
||||
asoc->shut_guard_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
|
||||
|
||||
asoc->delayed_event_timer.self = NULL;
|
||||
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
|
||||
SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
|
||||
net->fr_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
|
||||
net->rxt_timer.self = NULL;
|
||||
SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
|
||||
net->pmtu_timer.self = NULL;
|
||||
}
|
||||
/* Now the read queue needs to be cleaned up (only once) */
|
||||
cnt = 0;
|
||||
|
@ -105,6 +105,7 @@ sctp_do_peeloff(struct socket *head, struct socket *so, sctp_assoc_t assoc_id)
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
struct socket *
|
||||
sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
|
||||
{
|
||||
@ -177,6 +178,7 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
|
||||
SCTP_CLEAR_SO_NBIO(newso);
|
||||
newso->so_state |= SS_ISCONNECTED;
|
||||
/* We remove it right away */
|
||||
|
||||
#ifdef SCTP_LOCK_LOGGING
|
||||
sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
|
||||
#endif
|
||||
|
@ -460,9 +460,9 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
struct sctp_nets *lnets;
|
||||
struct timeval now, min_wait, tv;
|
||||
int cur_rtt;
|
||||
int orig_rwnd, audit_tf, num_mk, fir;
|
||||
int audit_tf, num_mk, fir;
|
||||
unsigned int cnt_mk;
|
||||
uint32_t orig_flight;
|
||||
uint32_t orig_flight, orig_tf;
|
||||
uint32_t tsnlast, tsnfirst;
|
||||
|
||||
/*
|
||||
@ -524,8 +524,9 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
* Our rwnd will be incorrect here since we are not adding back the
|
||||
* cnt * mbuf but we will fix that down below.
|
||||
*/
|
||||
orig_rwnd = stcb->asoc.peers_rwnd;
|
||||
orig_flight = net->flight_size;
|
||||
orig_tf = stcb->asoc.total_flight;
|
||||
|
||||
net->fast_retran_ip = 0;
|
||||
/* Now on to each chunk */
|
||||
num_mk = cnt_mk = 0;
|
||||
@ -617,7 +618,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (chk->sent != SCTP_DATAGRAM_RESEND) {
|
||||
if (chk->sent < SCTP_DATAGRAM_RESEND) {
|
||||
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
|
||||
num_mk++;
|
||||
if (fir == 0) {
|
||||
@ -630,33 +631,27 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
0, SCTP_FR_T3_MARKED);
|
||||
|
||||
#endif
|
||||
}
|
||||
if (stcb->asoc.total_flight_count > 0)
|
||||
stcb->asoc.total_flight_count--;
|
||||
if (chk->rec.data.chunk_was_revoked) {
|
||||
/* deflate the cwnd */
|
||||
chk->whoTo->cwnd -= chk->book_size;
|
||||
chk->rec.data.chunk_was_revoked = 0;
|
||||
if (chk->rec.data.chunk_was_revoked) {
|
||||
/* deflate the cwnd */
|
||||
chk->whoTo->cwnd -= chk->book_size;
|
||||
chk->rec.data.chunk_was_revoked = 0;
|
||||
}
|
||||
net->marked_retrans++;
|
||||
stcb->asoc.marked_retrans++;
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO,
|
||||
chk->whoTo->flight_size,
|
||||
chk->book_size,
|
||||
(uintptr_t) chk->whoTo,
|
||||
chk->rec.data.TSN_seq);
|
||||
#endif
|
||||
sctp_flight_size_decrease(chk);
|
||||
sctp_total_flight_decrease(stcb, chk);
|
||||
stcb->asoc.peers_rwnd += chk->send_size;
|
||||
stcb->asoc.peers_rwnd += sctp_peer_chunk_oh;
|
||||
}
|
||||
chk->sent = SCTP_DATAGRAM_RESEND;
|
||||
SCTP_STAT_INCR(sctps_markedretrans);
|
||||
net->marked_retrans++;
|
||||
stcb->asoc.marked_retrans++;
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN,
|
||||
chk->whoTo->flight_size,
|
||||
chk->book_size,
|
||||
(uintptr_t) stcb,
|
||||
chk->rec.data.TSN_seq);
|
||||
#endif
|
||||
|
||||
if (net->flight_size >= chk->book_size)
|
||||
net->flight_size -= chk->book_size;
|
||||
else
|
||||
net->flight_size = 0;
|
||||
|
||||
stcb->asoc.peers_rwnd += chk->send_size;
|
||||
stcb->asoc.peers_rwnd += sctp_peer_chunk_oh;
|
||||
|
||||
/* reset the TSN for striking and other FR stuff */
|
||||
chk->rec.data.doing_fast_retransmit = 0;
|
||||
@ -686,18 +681,13 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
cnt_mk++;
|
||||
}
|
||||
}
|
||||
if ((orig_flight - net->flight_size) != (orig_tf - stcb->asoc.total_flight)) {
|
||||
/* we did not subtract the same things? */
|
||||
audit_tf = 1;
|
||||
}
|
||||
#if defined(SCTP_FR_LOGGING) || defined(SCTP_EARLYFR_LOGGING)
|
||||
sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
|
||||
#endif
|
||||
|
||||
if (stcb->asoc.total_flight >= (orig_flight - net->flight_size)) {
|
||||
stcb->asoc.total_flight -= (orig_flight - net->flight_size);
|
||||
} else {
|
||||
stcb->asoc.total_flight = 0;
|
||||
stcb->asoc.total_flight_count = 0;
|
||||
audit_tf = 1;
|
||||
}
|
||||
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
|
||||
if (num_mk) {
|
||||
@ -766,12 +756,12 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
|
||||
chk->whoTo->flight_size,
|
||||
chk->book_size,
|
||||
(uintptr_t) stcb,
|
||||
(uintptr_t) chk->whoTo,
|
||||
chk->rec.data.TSN_seq);
|
||||
#endif
|
||||
stcb->asoc.total_flight += chk->book_size;
|
||||
chk->whoTo->flight_size += chk->book_size;
|
||||
stcb->asoc.total_flight_count++;
|
||||
|
||||
sctp_flight_size_increase(chk);
|
||||
sctp_total_flight_increase(stcb, chk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -865,7 +855,29 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
|
||||
} else {
|
||||
win_probe = 0;
|
||||
}
|
||||
alt = sctp_find_alternate_net(stcb, net, 0);
|
||||
|
||||
if (sctp_cmt_on_off) {
|
||||
/*
|
||||
* CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being
|
||||
* used, then pick dest with largest ssthresh for any
|
||||
* retransmission.
|
||||
*/
|
||||
alt = net;
|
||||
alt = sctp_find_alternate_net(stcb, alt, 1);
|
||||
/*
|
||||
* CUCv2: If a different dest is picked for the
|
||||
* retransmission, then new (rtx-)pseudo_cumack needs to be
|
||||
* tracked for orig dest. Let CUCv2 track new (rtx-)
|
||||
* pseudo-cumack always.
|
||||
*/
|
||||
net->find_pseudo_cumack = 1;
|
||||
net->find_rtx_pseudo_cumack = 1;
|
||||
|
||||
} else { /* CMT is OFF */
|
||||
|
||||
alt = sctp_find_alternate_net(stcb, net, 0);
|
||||
}
|
||||
|
||||
sctp_mark_all_for_resend(stcb, net, alt, win_probe, &num_mk);
|
||||
/* FR Loss recovery just ended with the T3. */
|
||||
stcb->asoc.fast_retran_loss_recovery = 0;
|
||||
|
@ -872,6 +872,7 @@ struct sctpstat {
|
||||
u_long sctps_sends_with_abort;
|
||||
u_long sctps_protocol_drain_calls;
|
||||
u_long sctps_protocol_drains_done;
|
||||
u_long sctps_read_peeks;
|
||||
};
|
||||
|
||||
#define SCTP_STAT_INCR(_x) SCTP_STAT_INCR_BY(_x,1)
|
||||
@ -971,8 +972,8 @@ sctp_lower_sosend(struct socket *so,
|
||||
struct mbuf *control,
|
||||
int flags,
|
||||
int use_rcvinfo,
|
||||
struct sctp_sndrcvinfo *srcv,
|
||||
struct thread *p
|
||||
struct sctp_sndrcvinfo *srcv
|
||||
,struct thread *p
|
||||
);
|
||||
|
||||
int
|
||||
|
@ -128,19 +128,17 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
|
||||
}
|
||||
chk->sent = SCTP_DATAGRAM_RESEND;
|
||||
chk->rec.data.doing_fast_retransmit = 0;
|
||||
|
||||
#ifdef SCTP_FLIGHT_LOGGING
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
|
||||
chk->whoTo->flight_size,
|
||||
chk->book_size,
|
||||
(uintptr_t) chk->whoTo,
|
||||
chk->rec.data.TSN_seq);
|
||||
#endif
|
||||
/* Clear any time so NO RTT is being done */
|
||||
chk->do_rtt = 0;
|
||||
if (stcb->asoc.total_flight >= chk->book_size)
|
||||
stcb->asoc.total_flight -= chk->book_size;
|
||||
else
|
||||
stcb->asoc.total_flight = 0;
|
||||
if (stcb->asoc.total_flight_count > 0)
|
||||
stcb->asoc.total_flight_count--;
|
||||
if (net->flight_size >= chk->book_size)
|
||||
net->flight_size -= chk->book_size;
|
||||
else
|
||||
net->flight_size = 0;
|
||||
sctp_flight_size_decrease(chk);
|
||||
sctp_total_flight_decrease(stcb, chk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,6 +231,57 @@ extern struct pr_usrreqs sctp_usrreqs;
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef RANDY_WILL_USE_LATER /* this will be the non-invarant version */
|
||||
#define sctp_flight_size_decrease(tp1) do { \
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size) \
|
||||
tp1->whoTo->flight_size -= tp1->book_size; \
|
||||
else \
|
||||
tp1->whoTo->flight_size = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define sctp_total_flight_decrease(stcb, tp1) do { \
|
||||
if (stcb->asoc.total_flight >= tp1->book_size) { \
|
||||
stcb->asoc.total_flight -= tp1->book_size; \
|
||||
if (stcb->asoc.total_flight_count > 0) \
|
||||
stcb->asoc.total_flight_count--; \
|
||||
} else { \
|
||||
stcb->asoc.total_flight = 0; \
|
||||
stcb->asoc.total_flight_count = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define sctp_flight_size_decrease(tp1) do { \
|
||||
if (tp1->whoTo->flight_size >= tp1->book_size) \
|
||||
tp1->whoTo->flight_size -= tp1->book_size; \
|
||||
else \
|
||||
panic("flight size corruption"); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define sctp_total_flight_decrease(stcb, tp1) do { \
|
||||
if (stcb->asoc.total_flight >= tp1->book_size) { \
|
||||
stcb->asoc.total_flight -= tp1->book_size; \
|
||||
if (stcb->asoc.total_flight_count > 0) \
|
||||
stcb->asoc.total_flight_count--; \
|
||||
} else { \
|
||||
panic("total flight size corruption"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define sctp_flight_size_increase(tp1) do { \
|
||||
(tp1)->whoTo->flight_size += (tp1)->book_size; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define sctp_total_flight_increase(stcb, tp1) do { \
|
||||
(stcb)->asoc.total_flight_count++; \
|
||||
(stcb)->asoc.total_flight += (tp1)->book_size; \
|
||||
} while (0)
|
||||
|
||||
struct sctp_nets;
|
||||
struct sctp_inpcb;
|
||||
|
@ -1404,7 +1404,9 @@ sctp_timeout_handler(void *t)
|
||||
}
|
||||
tmr->stopped_from = 0xa004;
|
||||
if (stcb) {
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
if (stcb->asoc.state == 0) {
|
||||
atomic_add_int(&stcb->asoc.refcnt, -1);
|
||||
if (inp) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
}
|
||||
@ -1426,7 +1428,6 @@ sctp_timeout_handler(void *t)
|
||||
tmr->stopped_from = 0xa006;
|
||||
|
||||
if (stcb) {
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_add_int(&stcb->asoc.refcnt, -1);
|
||||
}
|
||||
@ -2706,7 +2707,7 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
|
||||
*/
|
||||
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
|
||||
(event == SCTP_COMM_LOST)) {
|
||||
((event == SCTP_COMM_LOST) || (event == SCTP_SHUTDOWN_COMP))) {
|
||||
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT)
|
||||
stcb->sctp_socket->so_error = ECONNREFUSED;
|
||||
else
|
||||
@ -3270,7 +3271,12 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
case SCTP_NOTIFY_STRDATA_ERR:
|
||||
break;
|
||||
case SCTP_NOTIFY_ASSOC_ABORTED:
|
||||
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL);
|
||||
if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
|
||||
((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED))) {
|
||||
sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, NULL);
|
||||
} else {
|
||||
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL);
|
||||
}
|
||||
break;
|
||||
case SCTP_NOTIFY_PEER_OPENED_STREAM:
|
||||
break;
|
||||
@ -4488,6 +4494,8 @@ sctp_sorecvmsg(struct socket *so,
|
||||
|
||||
if (msg_flags) {
|
||||
in_flags = *msg_flags;
|
||||
if (in_flags & MSG_PEEK)
|
||||
SCTP_STAT_INCR(sctps_read_peeks);
|
||||
} else {
|
||||
in_flags = 0;
|
||||
}
|
||||
|
@ -31,33 +31,35 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
||||
#include <netinet/sctp_os.h>
|
||||
#include <sys/proc.h>
|
||||
#include <netinet/sctp_pcb.h>
|
||||
#include <netinet/sctp_header.h>
|
||||
#include <netinet/sctp_var.h>
|
||||
#if defined(INET6)
|
||||
#include <netinet6/sctp6_var.h>
|
||||
#endif
|
||||
#include <netinet/sctp_sysctl.h>
|
||||
#include <netinet/sctp_output.h>
|
||||
#include <netinet/sctp_input.h>
|
||||
#include <netinet/sctp_bsd_addr.h>
|
||||
#include <netinet/sctp_uio.h>
|
||||
#include <netinet/sctp_asconf.h>
|
||||
#include <netinet/sctputil.h>
|
||||
#include <netinet/sctp_indata.h>
|
||||
#include <netinet/sctp_asconf.h>
|
||||
#include <netinet/sctp_timer.h>
|
||||
#include <netinet/sctp_auth.h>
|
||||
#include <netinet6/sctp6_var.h>
|
||||
|
||||
#include <netinet/sctp_input.h>
|
||||
#include <netinet/sctp_output.h>
|
||||
|
||||
|
||||
extern struct protosw inetsw[];
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
sctp6_input(mp, offp, proto)
|
||||
struct mbuf **mp;
|
||||
sctp6_input(i_pak, offp, proto)
|
||||
struct mbuf **i_pak;
|
||||
int *offp;
|
||||
int proto;
|
||||
{
|
||||
@ -76,7 +78,8 @@ sctp6_input(mp, offp, proto)
|
||||
int off = *offp;
|
||||
|
||||
vrf_id = SCTP_DEFAULT_VRFID;
|
||||
m = SCTP_HEADER_TO_CHAIN(*mp);
|
||||
m = SCTP_HEADER_TO_CHAIN(*i_pak);
|
||||
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
/* Ensure that (sctphdr + sctp_chunkhdr) in a row. */
|
||||
@ -100,7 +103,9 @@ sctp6_input(mp, offp, proto)
|
||||
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
|
||||
#ifdef SCTP_DEBUG
|
||||
if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
|
||||
printf("V6 input gets a packet iphlen:%d pktlen:%d\n", iphlen, SCTP_HEADER_LEN((*mp)));
|
||||
printf("V6 input gets a packet iphlen:%d pktlen:%d\n", iphlen,
|
||||
SCTP_HEADER_LEN((*i_pak))
|
||||
);
|
||||
}
|
||||
#endif
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
@ -200,7 +205,6 @@ sctp6_input(mp, offp, proto)
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
|
||||
|
||||
/*
|
||||
* CONTROL chunk processing
|
||||
*/
|
||||
@ -682,7 +686,8 @@ sctp6_close(struct socket *so)
|
||||
|
||||
/* This could be made common with sctp_detach() since they are identical */
|
||||
|
||||
static int
|
||||
static
|
||||
int
|
||||
sctp6_disconnect(struct socket *so)
|
||||
{
|
||||
struct sctp_inpcb *inp;
|
||||
@ -715,23 +720,10 @@ sctp6_disconnect(struct socket *so)
|
||||
if (SCTP_GET_STATE(asoc) !=
|
||||
SCTP_STATE_COOKIE_WAIT) {
|
||||
/* Left with Data unread */
|
||||
struct mbuf *err;
|
||||
struct mbuf *op_err;
|
||||
|
||||
err = NULL;
|
||||
MGET(err, M_DONTWAIT, MT_DATA);
|
||||
if (err) {
|
||||
/*
|
||||
* Fill in the user
|
||||
* initiated abort
|
||||
*/
|
||||
struct sctp_paramhdr *ph;
|
||||
|
||||
ph = mtod(err, struct sctp_paramhdr *);
|
||||
SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
|
||||
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
|
||||
ph->param_length = htons(SCTP_BUF_LEN(err));
|
||||
}
|
||||
sctp_send_abort_tcb(stcb, err);
|
||||
op_err = sctp_generate_invmanparam(SCTP_CAUSE_USER_INITIATED_ABT);
|
||||
sctp_send_abort_tcb(stcb, op_err);
|
||||
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
|
||||
}
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
@ -803,6 +795,7 @@ sctp6_disconnect(struct socket *so)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
|
||||
struct mbuf *control, struct thread *p);
|
||||
@ -1221,6 +1214,7 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
|
||||
|
||||
in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
|
||||
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
|
||||
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
|
Loading…
Reference in New Issue
Block a user