aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/tsnmap.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2012-06-29 23:04:26 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-01 01:44:35 -0400
commit4244854d22bf8f782698c5224b9191c8d2d42610 (patch)
tree1c6d81517625a33e427a183587783a966960e135 /net/sctp/tsnmap.c
parent0e90b49ca4b891f085b57559a3071a4feefb496c (diff)
sctp: be more restrictive in transport selection on bundled sacks
It was noticed recently that when we send data on a transport, its possible that we might bundle a sack that arrived on a different transport. While this isn't a major problem, it does go against the SHOULD requirement in section 6.4 of RFC 2960: An endpoint SHOULD transmit reply chunks (e.g., SACK, HEARTBEAT ACK, etc.) to the same destination transport address from which it received the DATA or control chunk to which it is replying. This rule should also be followed if the endpoint is bundling DATA chunks together with the reply chunk. This patch seeks to correct that. It restricts the bundling of sack operations to only those transports which have moved the ctsn of the association forward since the last sack. By doing this we guarantee that we only bundle outbound saks on a transport that has received a chunk since the last sack. This brings us into stricter compliance with the RFC. Vlad had initially suggested that we strictly allow only sack bundling on the transport that last moved the ctsn forward. While this makes sense, I was concerned that doing so prevented us from bundling in the case where we had received chunks that moved the ctsn on multiple transports. In those cases, the RFC allows us to select any of the transports having received chunks to bundle the sack on. so I've modified the approach to allow for that, by adding a state variable to each transport that tracks weather it has moved the ctsn since the last sack. This I think keeps our behavior (and performance), close enough to our current profile that I think we can do this without a sysctl knob to enable/disable it. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> CC: Vlad Yaseivch <vyasevich@gmail.com> CC: David S. Miller <davem@davemloft.net> CC: linux-sctp@vger.kernel.org Reported-by: Michele Baldessari <michele@redhat.com> Reported-by: sorin serban <sserban@redhat.com> Acked-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/tsnmap.c')
-rw-r--r--net/sctp/tsnmap.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index f1e40cebc981..b5fb7c409023 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -114,7 +114,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn)
114 114
115 115
116/* Mark this TSN as seen. */ 116/* Mark this TSN as seen. */
117int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) 117int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,
118 struct sctp_transport *trans)
118{ 119{
119 u16 gap; 120 u16 gap;
120 121
@@ -133,6 +134,9 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn)
133 */ 134 */
134 map->max_tsn_seen++; 135 map->max_tsn_seen++;
135 map->cumulative_tsn_ack_point++; 136 map->cumulative_tsn_ack_point++;
137 if (trans)
138 trans->sack_generation =
139 trans->asoc->peer.sack_generation;
136 map->base_tsn++; 140 map->base_tsn++;
137 } else { 141 } else {
138 /* Either we already have a gap, or about to record a gap, so 142 /* Either we already have a gap, or about to record a gap, so