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 *); ...@@ -1613,6 +1613,7 @@ void sctp_association_put(sctp_association_t *);
void sctp_association_hold(sctp_association_t *); void sctp_association_hold(sctp_association_t *);
struct sctp_transport *sctp_assoc_choose_shutdown_transport(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 *, struct sctp_transport *sctp_assoc_lookup_paddr(const sctp_association_t *,
const union sctp_addr *); const union sctp_addr *);
struct sctp_transport *sctp_assoc_add_peer(sctp_association_t *, 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) ...@@ -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 * Round-robin through the active transports, else round-robin
* through the inactive transports as this is the next best thing * through the inactive transports as this is the next best thing
* we can try. * 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 sctp_transport *t, *next;
struct list_head *head = &asoc->peer.transport_addr_list; struct list_head *head = &asoc->peer.transport_addr_list;
struct list_head *pos; struct list_head *pos;
/* If this is the first time SHUTDOWN is sent, use the active /* Find the next transport in a round-robin fashion. */
* path. t = asoc->peer.retran_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;
pos = &t->transports; pos = &t->transports;
next = NULL; next = NULL;
...@@ -935,13 +928,30 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport(sctp_association_t * ...@@ -935,13 +928,30 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport(sctp_association_t *
* other active transports. If so, use the next * other active transports. If so, use the next
* transport. * transport.
*/ */
if (t == asoc->shutdown_last_sent_to) { if (t == asoc->peer.retran_path) {
t = next; t = next;
break; 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 /* 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) ...@@ -419,6 +419,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
dst = transport->dst; dst = transport->dst;
/* The 'obsolete' field of dst is set to 2 when a dst is freed. */ /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
if (!dst || (dst->obsolete > 1)) { if (!dst || (dst->obsolete > 1)) {
dst_release(dst);
sctp_transport_route(transport, NULL, sctp_sk(sk)); sctp_transport_route(transport, NULL, sctp_sk(sk));
sctp_assoc_sync_pmtu(asoc); sctp_assoc_sync_pmtu(asoc);
} }
......
...@@ -321,6 +321,11 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, ...@@ -321,6 +321,11 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport,
switch(reason) { switch(reason) {
case SCTP_RETRANSMIT_T3_RTX: case SCTP_RETRANSMIT_T3_RTX:
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_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; break;
case SCTP_RETRANSMIT_FAST_RTX: case SCTP_RETRANSMIT_FAST_RTX:
sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_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, ...@@ -449,7 +449,6 @@ struct dst_entry *sctp_v4_get_dst(sctp_association_t *asoc,
if (AF_INET == laddr->a.sa.sa_family) { if (AF_INET == laddr->a.sa.sa_family) {
fl.fl4_src = laddr->a.v4.sin_addr.s_addr; 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)) { if (!ip_route_output_key(&rt, &fl)) {
dst = &rt->u.dst; dst = &rt->u.dst;
goto out_unlock; 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