From 2cd9b822bfa79fc1335d3e71a0449f3cd0b5078e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 19 Jun 2008 17:59:13 -0400 Subject: sctp: Only mark chunks as missing when there are gaps Frist small step in optimizing SACK processing. Do not call sctp_mark_missing() when there are no gaps reported and thus not missing chunks. Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'net/sctp/outqueue.c') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 4328ad5439c9..ef5ea7423cc8 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1129,12 +1129,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) unsigned outstanding; struct sctp_transport *primary = asoc->peer.primary_path; int count_of_newacks = 0; + int gap_ack_blocks; /* Grab the association's destination address list. */ transport_list = &asoc->peer.transport_addr_list; sack_ctsn = ntohl(sack->cum_tsn_ack); - + gap_ack_blocks = ntohs(sack->num_gap_ack_blocks); /* * SFR-CACC algorithm: * On receipt of a SACK the sender SHOULD execute the @@ -1161,7 +1162,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) * A) Initialize the cacc_saw_newack to 0 for all destination * addresses. */ - if (sack->num_gap_ack_blocks && + if (gap_ack_blocks && primary->cacc.changeover_active) { list_for_each_entry(transport, transport_list, transports) { transport->cacc.cacc_saw_newack = 0; @@ -1170,9 +1171,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) /* Get the highest TSN in the sack. */ highest_tsn = sack_ctsn; - if (sack->num_gap_ack_blocks) - highest_tsn += - ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); + if (gap_ack_blocks) + highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); if (TSN_lt(asoc->highest_sacked, highest_tsn)) { highest_new_tsn = highest_tsn; @@ -1181,11 +1181,11 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) highest_new_tsn = sctp_highest_new_tsn(sack, asoc); } + /* Run through the retransmit queue. Credit bytes received * and free those chunks that we can. */ sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); - sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); /* Run through the transmitted queue. * Credit bytes received and free those chunks which we can. @@ -1204,9 +1204,12 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) count_of_newacks ++; } - list_for_each_entry(transport, transport_list, transports) { - sctp_mark_missing(q, &transport->transmitted, transport, - highest_new_tsn, count_of_newacks); + if (gap_ack_blocks) { + sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); + + list_for_each_entry(transport, transport_list, transports) + sctp_mark_missing(q, &transport->transmitted, transport, + highest_new_tsn, count_of_newacks); } /* Move the Cumulative TSN Ack Point if appropriate. */ -- cgit v1.2.3 From ab5216a5bd453752f04bb79c29e8f01b11d69006 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 19 Jun 2008 18:17:24 -0400 Subject: sctp: Optimize SFR-CACC transport list walking during SACK processing There is a possibility of walking the transport list twice during SACK processing when doing SFR-CACC algorithm. We can restructure the code to only do this once. Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'net/sctp/outqueue.c') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index ef5ea7423cc8..c8de4da57f36 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1145,27 +1145,31 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for * all destinations. - */ - if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { - primary->cacc.changeover_active = 0; - list_for_each_entry(transport, transport_list, - transports) { - transport->cacc.cycling_changeover = 0; - } - } - - /* - * SFR-CACC algorithm: * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE * is set the receiver of the SACK MUST take the following actions: * * A) Initialize the cacc_saw_newack to 0 for all destination * addresses. + * + * Only bother if changeover_active is set. Otherwise, this is + * totally suboptimal to do on every SACK. */ - if (gap_ack_blocks && - primary->cacc.changeover_active) { - list_for_each_entry(transport, transport_list, transports) { - transport->cacc.cacc_saw_newack = 0; + if (primary->cacc.changeover_active) { + u8 clear_cycling = 0; + + if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { + primary->cacc.changeover_active = 0; + clear_cycling = 1; + } + + if (clear_cycling || gap_ack_blocks) { + list_for_each_entry(transport, transport_list, + transports) { + if (clear_cycling) + transport->cacc.cycling_changeover = 0; + if (gap_ack_blocks) + transport->cacc.cacc_saw_newack = 0; + } } } -- cgit v1.2.3 From 845b8eda4d783a7ce2670d482a716840a650389e Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 23 Jun 2008 15:26:20 -0400 Subject: sctp: Retransmit list is ineligable for missing indications Chunks placed on the retransmit list are marked as inelegible for fast retrasnmission. Since missing indications determine when fast reransmission is done, there is not point in calling sctp_mark_missing() on the retransmit list since those chunks will not be marked. Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/sctp/outqueue.c') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index c8de4da57f36..da8d846301c1 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -1209,8 +1209,6 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) } if (gap_ack_blocks) { - sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); - list_for_each_entry(transport, transport_list, transports) sctp_mark_missing(q, &transport->transmitted, transport, highest_new_tsn, count_of_newacks); -- cgit v1.2.3 From c226ef9b83694311327f3ab0036c6de9c22e9daf Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 25 Jul 2008 12:44:09 -0400 Subject: sctp: reduce memory footprint of sctp_chunk structure sctp_chunks should be put on a diet. This is some of the low hanging fruit that we can strip out. Changes all the __s8/__u8 flags to bitfields. Saves 12 bytes per chunk. Signed-off-by: Neil Horman Signed-off-by: Vlad Yasevich --- net/sctp/outqueue.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'net/sctp/outqueue.c') diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index da8d846301c1..247ebc95c1e5 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -420,7 +420,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, * be added to the retransmit queue. */ if ((reason == SCTP_RTXR_FAST_RTX && - (chunk->fast_retransmit > 0)) || + (chunk->fast_retransmit == SCTP_NEED_FRTX)) || (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { /* If this chunk was sent less then 1 rto ago, do not * retransmit this chunk, but give the peer time @@ -650,8 +650,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, /* Mark the chunk as ineligible for fast retransmit * after it is retransmitted. */ - if (chunk->fast_retransmit > 0) - chunk->fast_retransmit = -1; + if (chunk->fast_retransmit == SCTP_NEED_FRTX) + chunk->fast_retransmit = SCTP_DONT_FRTX; /* Force start T3-rtx timer when fast retransmitting * the earliest outstanding TSN @@ -680,8 +680,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, */ if (rtx_timeout || fast_rtx) { list_for_each_entry(chunk1, lqueue, transmitted_list) { - if (chunk1->fast_retransmit > 0) - chunk1->fast_retransmit = -1; + if (chunk1->fast_retransmit == SCTP_NEED_FRTX) + chunk1->fast_retransmit = SCTP_DONT_FRTX; } } @@ -1656,7 +1656,7 @@ static void sctp_mark_missing(struct sctp_outq *q, * chunk if it has NOT been fast retransmitted or marked for * fast retransmit already. */ - if (!chunk->fast_retransmit && + if (chunk->fast_retransmit == SCTP_CAN_FRTX && !chunk->tsn_gap_acked && TSN_lt(tsn, highest_new_tsn_in_sack)) { @@ -1681,7 +1681,7 @@ static void sctp_mark_missing(struct sctp_outq *q, */ if (chunk->tsn_missing_report >= 3) { - chunk->fast_retransmit = 1; + chunk->fast_retransmit = SCTP_NEED_FRTX; do_fast_retransmit = 1; } } -- cgit v1.2.3