* Use exponential backoff for retransmission of SHUTDOWN and

SHUTDOWN-ACK chunks.
* While there, do some cleanups.

MFC after: 3 days.
This commit is contained in:
Michael Tuexen 2010-11-07 17:44:04 +00:00
parent 43b838f75c
commit b61c358887
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=214928

View File

@ -291,6 +291,10 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return (0);
}
/*
* sctp_find_alternate_net() returns a non-NULL pointer as long
* the argument net is non-NULL.
*/
struct sctp_nets *
sctp_find_alternate_net(struct sctp_tcb *stcb,
struct sctp_nets *net,
@ -440,8 +444,7 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
else if (mode == 1) {
TAILQ_FOREACH(mnet, &stcb->asoc.nets, sctp_next) {
if (((mnet->dest_state & SCTP_ADDR_REACHABLE) != SCTP_ADDR_REACHABLE) ||
(mnet->dest_state & SCTP_ADDR_UNCONFIRMED)
) {
(mnet->dest_state & SCTP_ADDR_UNCONFIRMED)) {
/*
* will skip ones that are not-reachable or
* unconfirmed
@ -505,12 +508,10 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
alt->src_addr_selected = 0;
}
if (
((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
(alt->ro.ro_rt != NULL) &&
/* sa_ignore NO_NULL_CHK */
(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))
) {
if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
(alt->ro.ro_rt != NULL) &&
(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) {
/* Found a reachable address */
break;
}
@ -549,8 +550,6 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
return (alt);
}
static void
sctp_backoff_on_timeout(struct sctp_tcb *stcb,
struct sctp_nets *net,
@ -1021,8 +1020,7 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
* used, then pick dest with largest ssthresh for any
* retransmission.
*/
alt = net;
alt = sctp_find_alternate_net(stcb, alt, 1);
alt = sctp_find_alternate_net(stcb, net, 1);
/*
* CUCv2: If a different dest is picked for the
* retransmission, then new (rtx-)pseudo_cumack needs to be
@ -1213,7 +1211,7 @@ sctp_t1init_timer(struct sctp_inpcb *inp,
struct sctp_nets *alt;
alt = sctp_find_alternate_net(stcb, stcb->asoc.primary_destination, 0);
if ((alt != NULL) && (alt != stcb->asoc.primary_destination)) {
if (alt != stcb->asoc.primary_destination) {
sctp_move_chunks_from_net(stcb, stcb->asoc.primary_destination);
stcb->asoc.primary_destination = alt;
}
@ -1480,6 +1478,7 @@ sctp_delete_prim_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* For the shutdown and shutdown-ack, we do not keep one around on the
* control queue. This means we must generate a new one and call the general
* chunk output routine, AFTER having done threshold management.
* It is assumed that net is non-NULL.
*/
int
sctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
@ -1492,18 +1491,13 @@ sctp_shutdown_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* Assoc is over */
return (1);
}
sctp_backoff_on_timeout(stcb, net, 1, 0, 0);
/* second select an alternative */
alt = sctp_find_alternate_net(stcb, net, 0);
/* third generate a shutdown into the queue for out net */
if (alt) {
sctp_send_shutdown(stcb, alt);
} else {
/*
* if alt is NULL, there is no dest to send to??
*/
return (0);
}
sctp_send_shutdown(stcb, alt);
/* fourth restart timer */
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, inp, stcb, alt);
return (0);
@ -1520,6 +1514,7 @@ sctp_shutdownack_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* Assoc is over */
return (1);
}
sctp_backoff_on_timeout(stcb, net, 1, 0, 0);
/* second select an alternative */
alt = sctp_find_alternate_net(stcb, net, 0);