diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2013-07-09 10:17:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-07-09 15:49:56 -0400 |
commit | 8c2f414ad1b3aa3af05791cd7312eb8ff9d80e0d (patch) | |
tree | 5d4281f3fbb68256211eaa2d39e45dc85c0874d8 /net/sctp/outqueue.c | |
parent | e1d6fbc3dedbb463fc79b48ddb05ab6b20fd088a (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.c | 9 |
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, | |||
1334 | __u8 restart_timer = 0; | 1334 | __u8 restart_timer = 0; |
1335 | int bytes_acked = 0; | 1335 | int bytes_acked = 0; |
1336 | int migrate_bytes = 0; | 1336 | int migrate_bytes = 0; |
1337 | bool forward_progress = false; | ||
1337 | 1338 | ||
1338 | sack_ctsn = ntohl(sack->cum_tsn_ack); | 1339 | sack_ctsn = ntohl(sack->cum_tsn_ack); |
1339 | 1340 | ||
@@ -1400,6 +1401,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1400 | bytes_acked += sctp_data_size(tchunk); | 1401 | bytes_acked += sctp_data_size(tchunk); |
1401 | if (!tchunk->transport) | 1402 | if (!tchunk->transport) |
1402 | migrate_bytes += sctp_data_size(tchunk); | 1403 | migrate_bytes += sctp_data_size(tchunk); |
1404 | forward_progress = true; | ||
1403 | } | 1405 | } |
1404 | 1406 | ||
1405 | if (TSN_lte(tsn, sack_ctsn)) { | 1407 | if (TSN_lte(tsn, sack_ctsn)) { |
@@ -1413,6 +1415,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1413 | * current RTO. | 1415 | * current RTO. |
1414 | */ | 1416 | */ |
1415 | restart_timer = 1; | 1417 | restart_timer = 1; |
1418 | forward_progress = true; | ||
1416 | 1419 | ||
1417 | if (!tchunk->tsn_gap_acked) { | 1420 | if (!tchunk->tsn_gap_acked) { |
1418 | /* | 1421 | /* |
@@ -1503,6 +1506,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1503 | */ | 1506 | */ |
1504 | transport->error_count = 0; | 1507 | transport->error_count = 0; |
1505 | transport->asoc->overall_error_count = 0; | 1508 | transport->asoc->overall_error_count = 0; |
1509 | forward_progress = true; | ||
1506 | 1510 | ||
1507 | /* | 1511 | /* |
1508 | * While in SHUTDOWN PENDING, we may have started | 1512 | * While in SHUTDOWN PENDING, we may have started |
@@ -1576,6 +1580,11 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
1576 | jiffies + transport->rto)) | 1580 | jiffies + transport->rto)) |
1577 | sctp_transport_hold(transport); | 1581 | sctp_transport_hold(transport); |
1578 | } | 1582 | } |
1583 | |||
1584 | if (forward_progress) { | ||
1585 | if (transport->dst) | ||
1586 | dst_confirm(transport->dst); | ||
1587 | } | ||
1579 | } | 1588 | } |
1580 | 1589 | ||
1581 | list_splice(&tlist, transmitted_queue); | 1590 | list_splice(&tlist, transmitted_queue); |