summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-06-19 18:17:24 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2008-10-01 11:33:06 -0400
commitab5216a5bd453752f04bb79c29e8f01b11d69006 (patch)
tree414dacc0b4275e9477d5d9f10f77a3543ee7cb96
parent2cd9b822bfa79fc1335d3e71a0449f3cd0b5078e (diff)
downloadlinux-ab5216a5bd453752f04bb79c29e8f01b11d69006.tar.gz
linux-ab5216a5bd453752f04bb79c29e8f01b11d69006.tar.bz2
linux-ab5216a5bd453752f04bb79c29e8f01b11d69006.zip
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 <vladislav.yasevich@hp.com>
-rw-r--r--net/sctp/outqueue.c34
1 files changed, 19 insertions, 15 deletions
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;
+ }
}
}