summaryrefslogtreecommitdiff
path: root/net/sctp/outqueue.c
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-07-09 16:17:04 +0200
committerDavid S. Miller <davem@davemloft.net>2013-07-09 12:49:56 -0700
commit8c2f414ad1b3aa3af05791cd7312eb8ff9d80e0d (patch)
tree5d4281f3fbb68256211eaa2d39e45dc85c0874d8 /net/sctp/outqueue.c
parente1d6fbc3dedbb463fc79b48ddb05ab6b20fd088a (diff)
net: sctp: confirm route during forward progress
This fix has been proposed originally by Vlad Yasevich. He says: When SCTP makes forward progress (receives a SACK that acks new chunks, renegs, or answeres 0-window probes) or when HB-ACK arrives, mark the route as confirmed so we don't unnecessarily send NUD probes. Having a simple SCTP client/server that exchange data chunks every 1sec, without this patch ARP requests are sent periodically every 40-60sec. With this fix applied, an ARP request is only done once right at the "session" beginning. Also, when clearing the related ARP cache entry manually during the session, a new request is correctly done. I have only "backported" this to net-next and tested that it works, so full credit goes to Vlad. Signed-off-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r--net/sctp/outqueue.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index cb80a8e060b7..ef9e2bbc0f2f 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1334,6 +1334,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
__u8 restart_timer = 0;
int bytes_acked = 0;
int migrate_bytes = 0;
+ bool forward_progress = false;
sack_ctsn = ntohl(sack->cum_tsn_ack);
@@ -1400,6 +1401,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
bytes_acked += sctp_data_size(tchunk);
if (!tchunk->transport)
migrate_bytes += sctp_data_size(tchunk);
+ forward_progress = true;
}
if (TSN_lte(tsn, sack_ctsn)) {
@@ -1413,6 +1415,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
* current RTO.
*/
restart_timer = 1;
+ forward_progress = true;
if (!tchunk->tsn_gap_acked) {
/*
@@ -1503,6 +1506,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
*/
transport->error_count = 0;
transport->asoc->overall_error_count = 0;
+ forward_progress = true;
/*
* While in SHUTDOWN PENDING, we may have started
@@ -1576,6 +1580,11 @@ static void sctp_check_transmitted(struct sctp_outq *q,
jiffies + transport->rto))
sctp_transport_hold(transport);
}
+
+ if (forward_progress) {
+ if (transport->dst)
+ dst_confirm(transport->dst);
+ }
}
list_splice(&tlist, transmitted_queue);