diff options
author | rrs <rrs@FreeBSD.org> | 2007-04-03 11:15:32 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2007-04-03 11:15:32 +0000 |
commit | ad3d5670174784e5b920754b5b0f8f9902669d09 (patch) | |
tree | a29f21245853449d39286dd5084db358d0ca42a9 /sys/netinet/sctp_indata.c | |
parent | c277843c2225aefe5e5c60e49de3fc0f95f7a798 (diff) | |
download | FreeBSD-src-ad3d5670174784e5b920754b5b0f8f9902669d09.zip FreeBSD-src-ad3d5670174784e5b920754b5b0f8f9902669d09.tar.gz |
- fixed several places where we did not release INP locks.
- fixed a refcount bug in the new ifa structures.
- use vrf's from default stcb or inp whenever possible.
- Address limits raised to account for a full IP fragmented
packet (1000 addresses).
- flight size correcting updated to include one message only
and to handle case where the peer does not cumack the
next segment aka lists 1/1 in sack blocks..
- Various bad init/init-ack handling could cause a panic
since we tried to unlock the destroyed mutex. Fixes
so we properly exit when we need to destroy an assoc.
(Found by Cisco DevTest team :D)
- name rename in src-addr-selection from pass to sifa.
- route structure typedef'd to allow different platforms
and updated into sctp_os_bsd file.
- Max retransmissions a chunk can be made added.
Reviewed by: gnn
Diffstat (limited to 'sys/netinet/sctp_indata.c')
-rw-r--r-- | sys/netinet/sctp_indata.c | 106 |
1 files changed, 93 insertions, 13 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index 462013e..4d142f7 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -4071,6 +4071,63 @@ skip_cwnd_update: } } +static int sctp_anal_print = 0; + +static void +sctp_print_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++; + } else if (chk->sent == SCTP_DATAGRAM_RESEND) { + resend++; + } else if (chk->sent < SCTP_DATAGRAM_ACKED) { + inbetween++; + } else if (chk->sent > SCTP_DATAGRAM_ACKED) { + 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); +} void sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, @@ -4081,7 +4138,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 j; + int j, done_once;; SCTP_TCB_LOCK_ASSERT(stcb); asoc = &stcb->asoc; @@ -4351,6 +4408,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack, win_probe_recovery = 1; } /* Now assure a timer where data is queued at */ + done_once = 0; again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { @@ -4402,12 +4460,15 @@ again: } } } - if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0)) { + if ((j == 0) && + (!TAILQ_EMPTY(&asoc->sent_queue)) && + (asoc->sent_queue_retran_cnt == 0) && + (done_once == 0)) { /* huh, this should not happen */ -#ifdef INVARIANTS - panic("Flight size incorrect? fixing??"); -#else - printf("Flight size incorrect? fixing\n"); + if (sctp_anal_print == 0) { + printf("Flight size-express incorrect? cumack:%x\n", cumack); + sctp_print_fs_audit(asoc); + } TAILQ_FOREACH(net, &asoc->nets, sctp_next) { net->flight_size = 0; } @@ -4423,7 +4484,12 @@ again: asoc->sent_queue_retran_cnt++; } } -#endif + 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; } /**********************************/ @@ -4527,6 +4593,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, *tp2; uint32_t cum_ack, last_tsn, biggest_tsn_acked, biggest_tsn_newly_acked, this_sack_lowest_newack; + uint32_t sav_cum_ack; uint16_t num_seg, num_dup; uint16_t wake_him = 0; unsigned int sack_length; @@ -4538,6 +4605,7 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, int win_probe_recovery = 0; struct sctp_nets *net = NULL; int nonce_sum_flag, ecn_seg_sums = 0; + int done_once; uint8_t reneged_all = 0; uint8_t cmt_dac_flag; @@ -4668,6 +4736,8 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb, /* acking something behind */ return; } + sav_cum_ack = asoc->last_acked_seq; + /* update the Rwnd of the peer */ if (TAILQ_EMPTY(&asoc->sent_queue) && TAILQ_EMPTY(&asoc->send_queue) && @@ -5391,6 +5461,7 @@ done_with_it: * Now we must setup so we have a timer up for anyone with * outstanding data. */ + done_once = 0; again: j = 0; TAILQ_FOREACH(net, &asoc->nets, sctp_next) { @@ -5423,12 +5494,16 @@ again: stcb->sctp_ep, stcb, net); } } - if ((j == 0) && (!TAILQ_EMPTY(&asoc->sent_queue)) && (asoc->sent_queue_retran_cnt == 0)) { + if ((j == 0) && + (!TAILQ_EMPTY(&asoc->sent_queue)) && + (asoc->sent_queue_retran_cnt == 0) && + (done_once == 0)) { /* huh, this should not happen */ -#ifdef INVARIANTS - panic("Flight size incorrect? fixing??"); -#else - printf("Flight size incorrect? fixing??\n"); + 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); + } TAILQ_FOREACH(net, &asoc->nets, sctp_next) { net->flight_size = 0; } @@ -5444,7 +5519,12 @@ again: asoc->sent_queue_retran_cnt++; } } -#endif + 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; } #ifdef SCTP_SACK_RWND_LOGGING |