aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2012-10-03 01:43:22 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-04 15:53:48 -0400
commitedfee0339e681a784ebacec7e8c2dc97dc6d2839 (patch)
treeec4c3953956d2de79ee326d08e46c6d9736a1068 /net
parent575659936f9d392b93b03ce97a58dbd4fce18abd (diff)
sctp: check src addr when processing SACK to update transport state
Suppose we have an SCTP connection with two paths. After connection is established, path1 is not available, thus this path is marked as inactive. Then traffic goes through path2, but for some reasons packets are delayed (after rto.max). Because packets are delayed, the retransmit mechanism will switch again to path1. At this time, we receive a delayed SACK from path2. When we update the state of the path in sctp_check_transmitted(), we do not take into account the source address of the SACK, hence we update the wrong path. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Acked-by: Vlad Yasevich <vyasevich@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sctp/outqueue.c15
-rw-r--r--net/sctp/sm_sideeffect.c4
-rw-r--r--net/sctp/sm_statefuns.c2
3 files changed, 13 insertions, 8 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index d16632e1503a..1b4a7f8ec3fd 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -63,6 +63,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
63static void sctp_check_transmitted(struct sctp_outq *q, 63static void sctp_check_transmitted(struct sctp_outq *q,
64 struct list_head *transmitted_queue, 64 struct list_head *transmitted_queue,
65 struct sctp_transport *transport, 65 struct sctp_transport *transport,
66 union sctp_addr *saddr,
66 struct sctp_sackhdr *sack, 67 struct sctp_sackhdr *sack,
67 __u32 *highest_new_tsn); 68 __u32 *highest_new_tsn);
68 69
@@ -1139,9 +1140,10 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc,
1139 * Process the SACK against the outqueue. Mostly, this just frees 1140 * Process the SACK against the outqueue. Mostly, this just frees
1140 * things off the transmitted queue. 1141 * things off the transmitted queue.
1141 */ 1142 */
1142int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) 1143int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
1143{ 1144{
1144 struct sctp_association *asoc = q->asoc; 1145 struct sctp_association *asoc = q->asoc;
1146 struct sctp_sackhdr *sack = chunk->subh.sack_hdr;
1145 struct sctp_transport *transport; 1147 struct sctp_transport *transport;
1146 struct sctp_chunk *tchunk = NULL; 1148 struct sctp_chunk *tchunk = NULL;
1147 struct list_head *lchunk, *transport_list, *temp; 1149 struct list_head *lchunk, *transport_list, *temp;
@@ -1210,7 +1212,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
1210 /* Run through the retransmit queue. Credit bytes received 1212 /* Run through the retransmit queue. Credit bytes received
1211 * and free those chunks that we can. 1213 * and free those chunks that we can.
1212 */ 1214 */
1213 sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn); 1215 sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn);
1214 1216
1215 /* Run through the transmitted queue. 1217 /* Run through the transmitted queue.
1216 * Credit bytes received and free those chunks which we can. 1218 * Credit bytes received and free those chunks which we can.
@@ -1219,7 +1221,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
1219 */ 1221 */
1220 list_for_each_entry(transport, transport_list, transports) { 1222 list_for_each_entry(transport, transport_list, transports) {
1221 sctp_check_transmitted(q, &transport->transmitted, 1223 sctp_check_transmitted(q, &transport->transmitted,
1222 transport, sack, &highest_new_tsn); 1224 transport, &chunk->source, sack,
1225 &highest_new_tsn);
1223 /* 1226 /*
1224 * SFR-CACC algorithm: 1227 * SFR-CACC algorithm:
1225 * C) Let count_of_newacks be the number of 1228 * C) Let count_of_newacks be the number of
@@ -1326,6 +1329,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q)
1326static void sctp_check_transmitted(struct sctp_outq *q, 1329static void sctp_check_transmitted(struct sctp_outq *q,
1327 struct list_head *transmitted_queue, 1330 struct list_head *transmitted_queue,
1328 struct sctp_transport *transport, 1331 struct sctp_transport *transport,
1332 union sctp_addr *saddr,
1329 struct sctp_sackhdr *sack, 1333 struct sctp_sackhdr *sack,
1330 __u32 *highest_new_tsn_in_sack) 1334 __u32 *highest_new_tsn_in_sack)
1331{ 1335{
@@ -1633,8 +1637,9 @@ static void sctp_check_transmitted(struct sctp_outq *q,
1633 /* Mark the destination transport address as 1637 /* Mark the destination transport address as
1634 * active if it is not so marked. 1638 * active if it is not so marked.
1635 */ 1639 */
1636 if ((transport->state == SCTP_INACTIVE) || 1640 if ((transport->state == SCTP_INACTIVE ||
1637 (transport->state == SCTP_UNCONFIRMED)) { 1641 transport->state == SCTP_UNCONFIRMED) &&
1642 sctp_cmp_addr_exact(&transport->ipaddr, saddr)) {
1638 sctp_assoc_control_transport( 1643 sctp_assoc_control_transport(
1639 transport->asoc, 1644 transport->asoc,
1640 transport, 1645 transport,
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index bcfebb91559d..57f7de839b03 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -752,11 +752,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
752/* Helper function to process the process SACK command. */ 752/* Helper function to process the process SACK command. */
753static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, 753static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
754 struct sctp_association *asoc, 754 struct sctp_association *asoc,
755 struct sctp_sackhdr *sackh) 755 struct sctp_chunk *chunk)
756{ 756{
757 int err = 0; 757 int err = 0;
758 758
759 if (sctp_outq_sack(&asoc->outqueue, sackh)) { 759 if (sctp_outq_sack(&asoc->outqueue, chunk)) {
760 struct net *net = sock_net(asoc->base.sk); 760 struct net *net = sock_net(asoc->base.sk);
761 761
762 /* There are no more TSNs awaiting SACK. */ 762 /* There are no more TSNs awaiting SACK. */
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 094813b6c3c3..b6adef8a1e93 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3179,7 +3179,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net,
3179 return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); 3179 return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
3180 3180
3181 /* Return this SACK for further processing. */ 3181 /* Return this SACK for further processing. */
3182 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); 3182 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk));
3183 3183
3184 /* Note: We do the rest of the work on the PROCESS_SACK 3184 /* Note: We do the rest of the work on the PROCESS_SACK
3185 * sideeffect. 3185 * sideeffect.