Commit 13970d8e authored by Sridhar Samudrala's avatar Sridhar Samudrala

[SCTP] Update retransmission path in a round-robin fashion when a

       retransmission timer expires instead of using the same path
       until the path error count reaches its threshold value.
parent 1cf4bfc4
......@@ -1613,6 +1613,7 @@ void sctp_association_put(sctp_association_t *);
void sctp_association_hold(sctp_association_t *);
struct sctp_transport *sctp_assoc_choose_shutdown_transport(sctp_association_t *);
void sctp_assoc_update_retran_path(sctp_association_t *);
struct sctp_transport *sctp_assoc_lookup_paddr(const sctp_association_t *,
const union sctp_addr *);
struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *,
......
......@@ -887,26 +887,19 @@ void sctp_assoc_update(sctp_association_t *asoc, sctp_association_t *new)
}
/* Choose the transport for sending a shutdown packet.
/* Update the retran path for sending a retransmitted packet.
* Round-robin through the active transports, else round-robin
* through the inactive transports as this is the next best thing
* we can try.
*/
struct sctp_transport *sctp_assoc_choose_shutdown_transport(sctp_association_t *asoc)
void sctp_assoc_update_retran_path(sctp_association_t *asoc)
{
struct sctp_transport *t, *next;
struct list_head *head = &asoc->peer.transport_addr_list;
struct list_head *pos;
/* If this is the first time SHUTDOWN is sent, use the active
* path.
*/
if (!asoc->shutdown_last_sent_to)
return asoc->peer.active_path;
/* Otherwise, find the next transport in a round-robin fashion. */
t = asoc->shutdown_last_sent_to;
/* Find the next transport in a round-robin fashion. */
t = asoc->peer.retran_path;
pos = &t->transports;
next = NULL;
......@@ -935,13 +928,30 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport(sctp_association_t *
* other active transports. If so, use the next
* transport.
*/
if (t == asoc->shutdown_last_sent_to) {
if (t == asoc->peer.retran_path) {
t = next;
break;
}
}
return t;
asoc->peer.retran_path = t;
}
/* Choose the transport for sending a SHUTDOWN packet. */
struct sctp_transport *sctp_assoc_choose_shutdown_transport(sctp_association_t *asoc)
{
/* If this is the first time SHUTDOWN is sent, use the active path,
* else use the retran path. If the last SHUTDOWN was sent over the
* retran path, update the retran path and use it.
*/
if (!asoc->shutdown_last_sent_to)
return asoc->peer.active_path;
else {
if (asoc->shutdown_last_sent_to == asoc->peer.retran_path)
sctp_assoc_update_retran_path(asoc);
return asoc->peer.retran_path;
}
}
/* Update the association's pmtu and frag_point by going through all the
......
......@@ -419,6 +419,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
dst = transport->dst;
/* The 'obsolete' field of dst is set to 2 when a dst is freed. */
if (!dst || (dst->obsolete > 1)) {
dst_release(dst);
sctp_transport_route(transport, NULL, sctp_sk(sk));
sctp_assoc_sync_pmtu(asoc);
}
......
......@@ -321,6 +321,11 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
switch(reason) {
case SCTP_RETRANSMIT_T3_RTX:
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX);
/* Update the retran path if the T3-rtx timer has expired for
* the current retran path.
*/
if (transport == transport->asoc->peer.retran_path)
sctp_assoc_update_retran_path(transport->asoc);
break;
case SCTP_RETRANSMIT_FAST_RTX:
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX);
......
......@@ -449,7 +449,6 @@ struct dst_entry *sctp_v4_get_dst(sctp_association_t *asoc,
if (AF_INET == laddr->a.sa.sa_family) {
fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
dst = sctp_v4_get_dst(asoc, daddr, &laddr->a);
if (!ip_route_output_key(&rt, &fl)) {
dst = &rt->u.dst;
goto out_unlock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment