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.
This commit is contained in:
parent
24f52bbd9b
commit
9eea4a2da7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212712
@ -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) {
|
||||
|
@ -79,8 +79,6 @@ extern void
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
}
|
||||
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 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
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 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb, struct sctp_nets *net,
|
||||
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 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
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 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
* 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 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
* 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 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
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 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
* 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 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
|
||||
} 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:
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -969,46 +969,6 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
|
||||
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)
|
||||
|
@ -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 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
|
||||
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++;
|
||||
|
Loading…
Reference in New Issue
Block a user