Skip to content

Commit edfee03

Browse files
NicolasDichteldavem330
authored andcommitted
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 <[email protected]> Acked-by: Vlad Yasevich <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5756599 commit edfee03

File tree

4 files changed

+14
-9
lines changed

4 files changed

+14
-9
lines changed

include/net/sctp/structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
10681068
void sctp_outq_teardown(struct sctp_outq *);
10691069
void sctp_outq_free(struct sctp_outq*);
10701070
int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk);
1071-
int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *);
1071+
int sctp_outq_sack(struct sctp_outq *, struct sctp_chunk *);
10721072
int sctp_outq_is_empty(const struct sctp_outq *);
10731073
void sctp_outq_restart(struct sctp_outq *);
10741074

net/sctp/outqueue.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
6363
static void sctp_check_transmitted(struct sctp_outq *q,
6464
struct list_head *transmitted_queue,
6565
struct sctp_transport *transport,
66+
union sctp_addr *saddr,
6667
struct sctp_sackhdr *sack,
6768
__u32 *highest_new_tsn);
6869

@@ -1139,9 +1140,10 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc,
11391140
* Process the SACK against the outqueue. Mostly, this just frees
11401141
* things off the transmitted queue.
11411142
*/
1142-
int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
1143+
int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
11431144
{
11441145
struct sctp_association *asoc = q->asoc;
1146+
struct sctp_sackhdr *sack = chunk->subh.sack_hdr;
11451147
struct sctp_transport *transport;
11461148
struct sctp_chunk *tchunk = NULL;
11471149
struct list_head *lchunk, *transport_list, *temp;
@@ -1210,7 +1212,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
12101212
/* Run through the retransmit queue. Credit bytes received
12111213
* and free those chunks that we can.
12121214
*/
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);
12141216

12151217
/* Run through the transmitted queue.
12161218
* 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)
12191221
*/
12201222
list_for_each_entry(transport, transport_list, transports) {
12211223
sctp_check_transmitted(q, &transport->transmitted,
1222-
transport, sack, &highest_new_tsn);
1224+
transport, &chunk->source, sack,
1225+
&highest_new_tsn);
12231226
/*
12241227
* SFR-CACC algorithm:
12251228
* C) Let count_of_newacks be the number of
@@ -1326,6 +1329,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q)
13261329
static void sctp_check_transmitted(struct sctp_outq *q,
13271330
struct list_head *transmitted_queue,
13281331
struct sctp_transport *transport,
1332+
union sctp_addr *saddr,
13291333
struct sctp_sackhdr *sack,
13301334
__u32 *highest_new_tsn_in_sack)
13311335
{
@@ -1633,8 +1637,9 @@ static void sctp_check_transmitted(struct sctp_outq *q,
16331637
/* Mark the destination transport address as
16341638
* active if it is not so marked.
16351639
*/
1636-
if ((transport->state == SCTP_INACTIVE) ||
1637-
(transport->state == SCTP_UNCONFIRMED)) {
1640+
if ((transport->state == SCTP_INACTIVE ||
1641+
transport->state == SCTP_UNCONFIRMED) &&
1642+
sctp_cmp_addr_exact(&transport->ipaddr, saddr)) {
16381643
sctp_assoc_control_transport(
16391644
transport->asoc,
16401645
transport,

net/sctp/sm_sideeffect.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,11 +752,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
752752
/* Helper function to process the process SACK command. */
753753
static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds,
754754
struct sctp_association *asoc,
755-
struct sctp_sackhdr *sackh)
755+
struct sctp_chunk *chunk)
756756
{
757757
int err = 0;
758758

759-
if (sctp_outq_sack(&asoc->outqueue, sackh)) {
759+
if (sctp_outq_sack(&asoc->outqueue, chunk)) {
760760
struct net *net = sock_net(asoc->base.sk);
761761

762762
/* There are no more TSNs awaiting SACK. */

net/sctp/sm_statefuns.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3179,7 +3179,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net,
31793179
return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands);
31803180

31813181
/* 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));
31833183

31843184
/* Note: We do the rest of the work on the PROCESS_SACK
31853185
* sideeffect.

0 commit comments

Comments
 (0)