From f2b48f2eb41188c13d865ca9bc48591e772ed6af Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Tue, 11 Feb 2003 18:46:31 -0800 Subject: [SCTP] sctp mib statistics update/display support. --- net/sctp/outqueue.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'net/sctp/outqueue.c') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index b1bfe69e61ed..a5019f6d7bdd 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -193,11 +193,17 @@ int sctp_outq_tail(struct sctp_outq *q, sctp_chunk_t *chunk) : "Illegal Chunk"); skb_queue_tail(&q->out, (struct sk_buff *) chunk); + if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) + SCTP_INC_STATS(SctpOutUnorderChunks); + else + SCTP_INC_STATS(SctpOutOrderChunks); q->empty = 0; break; }; - } else + } else { skb_queue_tail(&q->control, (struct sk_buff *) chunk); + SCTP_INC_STATS(SctpOutCtrlChunks); + } if (error < 0) return error; -- cgit v1.2.3 From 13970d8e1ff3451967050309ce14ae2b6160bfd5 Mon Sep 17 00:00:00 2001 From: Sridhar Samudrala Date: Mon, 17 Feb 2003 00:33:37 -0800 Subject: [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. --- include/net/sctp/structs.h | 1 + net/sctp/associola.c | 36 +++++++++++++++++++++++------------- net/sctp/output.c | 1 + net/sctp/outqueue.c | 5 +++++ net/sctp/protocol.c | 1 - 5 files changed, 30 insertions(+), 14 deletions(-) (limited to 'net/sctp/outqueue.c') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index bcb994fad15b..d136122af892 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -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 *, diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f8f9ed0138bd..916c11d97ac1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -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 diff --git a/net/sctp/output.c b/net/sctp/output.c index 9dcbc6d38a1f..d7826c2216e6 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -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); } diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index a5019f6d7bdd..1171984c3e20 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -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); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index b69dff403d61..85a5a2941af5 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -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; -- cgit v1.2.3