From 790dcded4d97b3159e5d8054665dac9b6202a524 Mon Sep 17 00:00:00 2001 From: tuexen Date: Wed, 15 Sep 2010 23:10:45 +0000 Subject: Delay the assignment of a path for DATA chunk until they hit the sent_queue. Honor a given path when the SCTP_ADDR_OVER flag is set. MFC after: 2 weeks. --- sys/netinet/sctp_asconf.c | 47 +------------ sys/netinet/sctp_asconf.h | 2 - sys/netinet/sctp_input.c | 17 +++-- sys/netinet/sctp_output.c | 165 ++++++++++++++++++++++------------------------ sys/netinet/sctp_output.h | 2 + sys/netinet/sctp_pcb.c | 10 ++- sys/netinet/sctp_timer.c | 49 ++------------ sys/netinet/sctputil.c | 11 ++-- 8 files changed, 112 insertions(+), 191 deletions(-) (limited to 'sys') diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index ee5dc0d..288381d 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -581,8 +581,8 @@ sctp_process_asconf_set_primary(struct mbuf *m, } if (sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_BASE)) { - sctp_move_chunks_from_deleted_prim(stcb, - stcb->asoc.primary_destination); + sctp_move_chunks_from_net(stcb, + stcb->asoc.deleted_primary); } sctp_delete_prim_timer(stcb->sctp_ep, stcb, stcb->asoc.deleted_primary); @@ -1041,47 +1041,6 @@ sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn) } } -void -sctp_move_chunks_from_deleted_prim(struct sctp_tcb *stcb, struct sctp_nets *dst) -{ - struct sctp_association *asoc; - struct sctp_stream_out *outs; - struct sctp_tmit_chunk *chk; - struct sctp_stream_queue_pending *sp; - - if (dst->dest_state & SCTP_ADDR_UNCONFIRMED) { - return; - } - if (stcb->asoc.deleted_primary == NULL) { - return; - } - asoc = &stcb->asoc; - - /* - * now through all the streams checking for chunks sent to our bad - * network. - */ - TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) { - /* now clean up any chunks here */ - TAILQ_FOREACH(sp, &outs->outqueue, next) { - if (sp->net == asoc->deleted_primary) { - sctp_free_remote_addr(sp->net); - sp->net = dst; - atomic_add_int(&dst->ref_count, 1); - } - } - } - /* Now check the pending queue */ - TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { - if (chk->whoTo == asoc->deleted_primary) { - sctp_free_remote_addr(chk->whoTo); - chk->whoTo = dst; - atomic_add_int(&dst->ref_count, 1); - } - } - -} - void sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet) @@ -2080,13 +2039,11 @@ sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val) struct sctp_asconf_iterator *asc; struct sctp_ifa *ifa; struct sctp_laddr *l; - int type; int cnt_invalid = 0; asc = (struct sctp_asconf_iterator *)ptr; LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) { ifa = l->ifa; - type = l->action; if (ifa->address.sa.sa_family == AF_INET6) { /* invalid if we're not a v6 endpoint */ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { diff --git a/sys/netinet/sctp_asconf.h b/sys/netinet/sctp_asconf.h index 9622871..bf3d566 100644 --- a/sys/netinet/sctp_asconf.h +++ b/sys/netinet/sctp_asconf.h @@ -80,8 +80,6 @@ sctp_check_address_list(struct sctp_tcb *, struct mbuf *, int, int, struct sockaddr *, uint16_t, uint16_t, uint16_t, uint16_t); extern void - sctp_move_chunks_from_deleted_prim(struct sctp_tcb *, struct sctp_nets *); -extern void sctp_assoc_immediate_retrans(struct sctp_tcb *, struct sctp_nets *); extern void sctp_net_immediate_retrans(struct sctp_tcb *, struct sctp_nets *); diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index a7b8e7f..8dffd4d 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -232,7 +232,10 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb) } atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); - sctp_free_remote_addr(sp->net); + if (sp->net) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; + } if (sp->data) { sctp_m_freem(sp->data); sp->data = NULL; @@ -263,7 +266,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb, /* save off parameters */ asoc->peer_vtag = ntohl(init->initiate_tag); asoc->peers_rwnd = ntohl(init->a_rwnd); - if (TAILQ_FIRST(&asoc->nets)) { + if (!TAILQ_EMPTY(&asoc->nets)) { /* update any ssthresh's that may have a default */ TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { lnet->ssthresh = asoc->peers_rwnd; @@ -318,8 +321,10 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb, sctp_m_freem(sp->data); sp->data = NULL; } - sctp_free_remote_addr(sp->net); - sp->net = NULL; + if (sp->net) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; + } /* Free the chunk */ sctp_free_a_strmoq(stcb, sp); /* sa_ignore FREED_MEMORY */ @@ -650,8 +655,8 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, } if (sctp_is_mobility_feature_on(stcb->sctp_ep, SCTP_MOBILITY_BASE)) { - sctp_move_chunks_from_deleted_prim(stcb, - stcb->asoc.primary_destination); + sctp_move_chunks_from_net(stcb, + stcb->asoc.deleted_primary); } sctp_delete_prim_timer(stcb->sctp_ep, stcb, stcb->asoc.deleted_primary); diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index d4db0e2..ac141bc 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5911,10 +5911,10 @@ sctp_msg_append(struct sctp_tcb *stcb, sp->strseq = 0; if (sp->sinfo_flags & SCTP_ADDR_OVER) { sp->net = net; + atomic_add_int(&sp->net->ref_count, 1); } else { - sp->net = stcb->asoc.primary_destination; + sp->net = NULL; } - atomic_add_int(&sp->net->ref_count, 1); (void)SCTP_GETTIME_TIMEVAL(&sp->ts); sp->stream = srcv->sinfo_stream; sp->msg_is_complete = 1; @@ -6513,7 +6513,6 @@ sctp_toss_old_asconf(struct sctp_tcb *stcb) static void sctp_clean_up_datalist(struct sctp_tcb *stcb, - struct sctp_association *asoc, struct sctp_tmit_chunk **data_list, int bundle_at, @@ -6524,7 +6523,9 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb, for (i = 0; i < bundle_at; i++) { /* off of the send queue */ - if (i) { + TAILQ_REMOVE(&asoc->send_queue, data_list[i], sctp_next); + asoc->send_queue_cnt--; + if (i > 0) { /* * Any chunk NOT 0 you zap the time chunk 0 gets * zapped or set based on if a RTO measurment is @@ -6535,9 +6536,10 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb, /* record time */ data_list[i]->sent_rcv_time = net->last_sent_time; data_list[i]->rec.data.fast_retran_tsn = data_list[i]->rec.data.TSN_seq; - TAILQ_REMOVE(&asoc->send_queue, - data_list[i], - sctp_next); + if (data_list[i]->whoTo == NULL) { + data_list[i]->whoTo = net; + atomic_add_int(&net->ref_count, 1); + } /* on to the sent queue */ tp1 = TAILQ_LAST(&asoc->sent_queue, sctpchunk_listhead); if ((tp1) && (compare_with_wrap(tp1->rec.data.TSN_seq, @@ -6565,7 +6567,6 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb, all_done: /* This does not lower until the cum-ack passes it */ asoc->sent_queue_cnt++; - asoc->send_queue_cnt--; if ((asoc->peers_rwnd <= 0) && (asoc->total_flight == 0) && (bundle_at == 1)) { @@ -6703,7 +6704,7 @@ sctp_can_we_split_this(struct sctp_tcb *stcb, } static uint32_t -sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net, +sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_stream_out *strq, uint32_t goal_mtu, uint32_t frag_point, @@ -6772,7 +6773,10 @@ one_more_time: } atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&strq->outqueue, sp, next); - sctp_free_remote_addr(sp->net); + if (sp->net) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; + } if (sp->data) { sctp_m_freem(sp->data); sp->data = NULL; @@ -7089,8 +7093,11 @@ dont_do_it: chk->rec.data.timetodrop = sp->ts; chk->flags = sp->act_flags; - chk->whoTo = net; - atomic_add_int(&chk->whoTo->ref_count, 1); + if (sp->net) { + chk->whoTo = sp->net; + atomic_add_int(&chk->whoTo->ref_count, 1); + } else + chk->whoTo = NULL; if (sp->holds_key_ref) { chk->auth_keyid = sp->auth_keyid; @@ -7175,7 +7182,10 @@ dont_do_it: send_lock_up = 1; } TAILQ_REMOVE(&strq->outqueue, sp, next); - sctp_free_remote_addr(sp->net); + if (sp->net) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; + } if (sp->data) { sctp_m_freem(sp->data); sp->data = NULL; @@ -7248,31 +7258,29 @@ sctp_fill_outqueue(struct sctp_tcb *stcb, goal_mtu &= 0xfffffffc; if (asoc->locked_on_sending) { /* We are stuck on one stream until the message completes. */ - strqn = strq = asoc->locked_on_sending; + strq = asoc->locked_on_sending; locked = 1; } else { - strqn = strq = sctp_select_a_stream(stcb, asoc); + strq = sctp_select_a_stream(stcb, asoc); locked = 0; } - + strqn = strq; while ((goal_mtu > 0) && strq) { sp = TAILQ_FIRST(&strq->outqueue); - /* - * If CMT is off, we must validate that the stream in - * question has the first item pointed towards are network - * destionation requested by the caller. Note that if we - * turn out to be locked to a stream (assigning TSN's then - * we must stop, since we cannot look for another stream - * with data to send to that destination). In CMT's case, by - * skipping this check, we will send one data packet towards - * the requested net. - */ if (sp == NULL) { break; } - if ((sp->net != net) && - (asoc->sctp_cmt_on_off == 0)) { - /* none for this network */ + /** + * Honor the users' choice if given. If not given, + * pull it only to the primary path in case of not using + * CMT. + */ + if (((sp->net != NULL) && + (sp->net != net)) || + ((sp->net == NULL) && + (asoc->sctp_cmt_on_off == 0) && + (asoc->primary_destination != net))) { + /* Do not pull to this network */ if (locked) { break; } else { @@ -7289,7 +7297,7 @@ sctp_fill_outqueue(struct sctp_tcb *stcb, } giveup = 0; bail = 0; - moved_how_much = sctp_move_to_outqueue(stcb, net, strq, goal_mtu, frag_point, &locked, + moved_how_much = sctp_move_to_outqueue(stcb, strq, goal_mtu, frag_point, &locked, &giveup, eeor_mode, &bail); if (moved_how_much) asoc->last_out_stream = strq; @@ -7353,43 +7361,32 @@ sctp_fix_ecn_echo(struct sctp_association *asoc) } } -static void -sctp_move_to_an_alt(struct sctp_tcb *stcb, - struct sctp_association *asoc, - struct sctp_nets *net) +void +sctp_move_chunks_from_net(struct sctp_tcb *stcb, struct sctp_nets *net) { + struct sctp_association *asoc; + struct sctp_stream_out *outs; struct sctp_tmit_chunk *chk; - struct sctp_nets *a_net; + struct sctp_stream_queue_pending *sp; - SCTP_TCB_LOCK_ASSERT(stcb); - /* - * JRS 5/14/07 - If CMT PF is turned on, find an alternate - * destination using the PF algorithm for finding alternate - * destinations. - */ - if ((asoc->sctp_cmt_on_off == 1) && - (asoc->sctp_cmt_pf > 0)) { - a_net = sctp_find_alternate_net(stcb, net, 2); - } else { - a_net = sctp_find_alternate_net(stcb, net, 0); + if (net == NULL) { + return; } - if ((a_net != net) && - ((a_net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE)) { - /* - * We only proceed if a valid alternate is found that is not - * this one and is reachable. Here we must move all chunks - * queued in the send queue off of the destination address - * to our alternate. - */ - TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { - if (chk->whoTo == net) { - /* Move the chunk to our alternate */ - sctp_free_remote_addr(chk->whoTo); - chk->whoTo = a_net; - atomic_add_int(&a_net->ref_count, 1); + asoc = &stcb->asoc; + TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) { + TAILQ_FOREACH(sp, &outs->outqueue, next) { + if (sp->net == net) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; } } } + TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { + if (chk->whoTo == net) { + sctp_free_remote_addr(chk->whoTo); + chk->whoTo = NULL; + } + } } int @@ -7497,7 +7494,8 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, * copy by reference (we hope). */ net->window_probe = 0; - if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) || (net->dest_state & SCTP_ADDR_UNCONFIRMED)) { + if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) || + (net->dest_state & SCTP_ADDR_UNCONFIRMED)) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { sctp_log_cwnd(stcb, net, 1, SCTP_CWND_LOG_FILL_OUTQ_CALLED); @@ -7505,6 +7503,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, continue; } if ((asoc->sctp_cmt_on_off == 0) && + (asoc->primary_destination != net) && (net->ref_count < 2)) { /* nothing can be in queue for this guy */ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) { @@ -7534,9 +7533,9 @@ sctp_med_chunk_output(struct sctp_inpcb *inp, } /* now service each destination and send out what we can for it */ /* Nothing to send? */ - if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) && - (TAILQ_FIRST(&asoc->asconf_send_queue) == NULL) && - (TAILQ_FIRST(&asoc->send_queue) == NULL)) { + if (TAILQ_EMPTY(&asoc->control_send_queue) && + TAILQ_EMPTY(&asoc->asconf_send_queue) && + TAILQ_EMPTY(&asoc->send_queue)) { *reason_code = 8; return (0); } @@ -7566,15 +7565,17 @@ again_one_more_time: break; } tsns_sent = 0xa; - if ((asoc->sctp_cmt_on_off == 0) && (net->ref_count < 2)) { + if ((asoc->sctp_cmt_on_off == 0) && + (asoc->primary_destination != net) && + (net->ref_count < 2)) { /* * Ref-count of 1 so we cannot have data or control * queued to this address. Skip it (non-CMT). */ continue; } - if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) && - (TAILQ_FIRST(&asoc->asconf_send_queue) == NULL) && + if (TAILQ_EMPTY(&asoc->control_send_queue) && + TAILQ_EMPTY(&asoc->asconf_send_queue) && (net->flight_size >= net->cwnd)) { /* * Nothing on control or asconf and flight is full, @@ -7778,7 +7779,7 @@ again_one_more_time: * unreachable * during this send */ - sctp_move_to_an_alt(stcb, asoc, net); + sctp_move_chunks_from_net(stcb, net); } *reason_code = 7; continue; @@ -8001,7 +8002,7 @@ again_one_more_time: * unreachable * during this send */ - sctp_move_to_an_alt(stcb, asoc, net); + sctp_move_chunks_from_net(stcb, net); } *reason_code = 7; continue; @@ -8102,19 +8103,9 @@ again_one_more_time: break; } nchk = TAILQ_NEXT(chk, sctp_next); - if (asoc->sctp_cmt_on_off == 1) { - if (chk->whoTo != net) { - /* - * For CMT, steal the data - * to this network if its - * not set here. - */ - sctp_free_remote_addr(chk->whoTo); - chk->whoTo = net; - atomic_add_int(&chk->whoTo->ref_count, 1); - } - } else if (chk->whoTo != net) { - /* No, not sent to this net */ + if ((chk->whoTo != NULL) && + (chk->whoTo != net)) { + /* Don't send the chunk on this net */ continue; } if ((chk->send_size > omtu) && ((chk->flags & CHUNK_FLAGS_FRAGMENT_OK) == 0)) { @@ -8330,7 +8321,7 @@ no_data_fill: * Destination went unreachable * during this send */ - sctp_move_to_an_alt(stcb, asoc, net); + sctp_move_chunks_from_net(stcb, net); } *reason_code = 6; /*- @@ -9584,7 +9575,7 @@ sctp_chunk_output(struct sctp_inpcb *inp, * out wheel to this alternate address. */ if (net->ref_count > 1) - sctp_move_to_an_alt(stcb, asoc, net); + sctp_move_chunks_from_net(stcb, net); } else if ((asoc->sctp_cmt_on_off == 1) && (asoc->sctp_cmt_pf > 0) && ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) { @@ -9594,7 +9585,7 @@ sctp_chunk_output(struct sctp_inpcb *inp, * to an alternate desination. */ if (net->ref_count > 1) - sctp_move_to_an_alt(stcb, asoc, net); + sctp_move_chunks_from_net(stcb, net); } else { /*- * if ((asoc->sat_network) || (net->addr_is_local)) @@ -12103,10 +12094,10 @@ skip_copy: } else { if (sp->sinfo_flags & SCTP_ADDR_OVER) { sp->net = net; + atomic_add_int(&sp->net->ref_count, 1); } else { - sp->net = asoc->primary_destination; + sp->net = NULL; } - atomic_add_int(&sp->net->ref_count, 1); sctp_set_prsctp_policy(sp); } out_now: diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h index 6488b1c..d655c3a 100644 --- a/sys/netinet/sctp_output.h +++ b/sys/netinet/sctp_output.h @@ -129,6 +129,8 @@ void sctp_toss_old_asconf(struct sctp_tcb *); void sctp_fix_ecn_echo(struct sctp_association *); +void sctp_move_chunks_from_net(struct sctp_tcb *stcb, struct sctp_nets *net); + int sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *, int); diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index de18c2e..e7b5553 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -4843,7 +4843,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre sp->tail_mbuf = NULL; } } - sctp_free_remote_addr(sp->net); + if (sp->net) { + sctp_free_remote_addr(sp->net); + sp->net = NULL; + } sctp_free_spbufspace(stcb, asoc, sp); if (sp->holds_key_ref) sctp_auth_key_release(stcb, sp->auth_keyid); @@ -4914,7 +4917,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre if (chk->holds_key_ref) sctp_auth_key_release(stcb, chk->auth_keyid); ccnt++; - sctp_free_remote_addr(chk->whoTo); + if (chk->whoTo) { + sctp_free_remote_addr(chk->whoTo); + chk->whoTo = NULL; + } SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); SCTP_DECR_CHK_COUNT(); /* sa_ignore FREED_MEMORY */ diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index 1e0b771..6db5193 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -969,46 +969,6 @@ start_again: return (0); } -static void -sctp_move_all_chunks_to_alt(struct sctp_tcb *stcb, - struct sctp_nets *net, - struct sctp_nets *alt) -{ - struct sctp_association *asoc; - struct sctp_stream_out *outs; - struct sctp_tmit_chunk *chk; - struct sctp_stream_queue_pending *sp; - - if (net == alt) - /* nothing to do */ - return; - - asoc = &stcb->asoc; - - /* - * now through all the streams checking for chunks sent to our bad - * network. - */ - TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) { - /* now clean up any chunks here */ - TAILQ_FOREACH(sp, &outs->outqueue, next) { - if (sp->net == net) { - sctp_free_remote_addr(sp->net); - sp->net = alt; - atomic_add_int(&alt->ref_count, 1); - } - } - } - /* Now check the pending queue */ - TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { - if (chk->whoTo == net) { - sctp_free_remote_addr(chk->whoTo); - chk->whoTo = alt; - atomic_add_int(&alt->ref_count, 1); - } - } - -} int sctp_t3rxt_timer(struct sctp_inpcb *inp, @@ -1141,7 +1101,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp, } if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) { /* Move all pending over too */ - sctp_move_all_chunks_to_alt(stcb, net, alt); + sctp_move_chunks_from_net(stcb, net); /* * Get the address that failed, to force a new src address @@ -1256,7 +1216,7 @@ sctp_t1init_timer(struct sctp_inpcb *inp, alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination, 0); if ((alt != NULL) && (alt != stcb->asoc.primary_destination)) { - sctp_move_all_chunks_to_alt(stcb, stcb->asoc.primary_destination, alt); + sctp_move_chunks_from_net(stcb, stcb->asoc.primary_destination); stcb->asoc.primary_destination = alt; } } @@ -1396,7 +1356,7 @@ sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * If the address went un-reachable, we need to move to * alternates for ALL chk's in queue */ - sctp_move_all_chunks_to_alt(stcb, net, alt); + sctp_move_chunks_from_net(stcb, net); } /* mark the retran info */ if (strrst->sent != SCTP_DATAGRAM_RESEND) @@ -1487,8 +1447,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb, * If the address went un-reachable, we need to move * to the alternate for ALL chunks in queue */ - sctp_move_all_chunks_to_alt(stcb, net, alt); - net = alt; + sctp_move_chunks_from_net(stcb, net); } /* mark the retran info */ if (asconf->sent != SCTP_DATAGRAM_RESEND) diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c index b09fe7e..543967a 100644 --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -2500,7 +2500,6 @@ sctp_mtu_size_reset(struct sctp_inpcb *inp, } eff_mtu = mtu - ovh; TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { - if (chk->send_size > eff_mtu) { chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; } @@ -3763,9 +3762,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked sp->data = NULL; } } - if (sp->net) + if (sp->net) { sctp_free_remote_addr(sp->net); - sp->net = NULL; + sp->net = NULL; + } /* Free the chunk */ sctp_free_a_strmoq(stcb, sp); /* sa_ignore FREED_MEMORY */ @@ -4818,7 +4818,10 @@ next_on_sent: chk->rec.data.payloadtype = sp->ppid; chk->rec.data.context = sp->context; chk->flags = sp->act_flags; - chk->whoTo = sp->net; + if (sp->net) + chk->whoTo = sp->net; + else + chk->whoTo = stcb->asoc.primary_destination; atomic_add_int(&chk->whoTo->ref_count, 1); chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); stcb->asoc.pr_sctp_cnt++; -- cgit v1.1