Skip to content

Commit 38bffef

Browse files
Merge DAC algorithm to main branch.
The algorithms applied: 1) DAC 2) CUC 3) RTX Balancer The performance boost is not very outstanding comparing to SFR. The original SCTP implementation would not delay ACK when unordered TSNs delivery happens. This phenomenom is common for CMT. Change that later and with more experiment.
1 parent ad9e464 commit 38bffef

File tree

5 files changed

+106
-11
lines changed

5 files changed

+106
-11
lines changed

include/net/sctp/cmt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,10 @@ extern char* cmt_print_sackhdr(struct sctp_sackhdr *sack);
3333
extern char* cmt_print_queued_tsn(struct list_head *queue, struct sctp_transport *transport);
3434

3535
extern char* cmt_print_cwnd(struct list_head *transport_list);
36+
37+
/* SACK Chunk Specific Flags*/
38+
enum {
39+
SCTP_SACK_NUM_PDU_BEG = 6,
40+
SCTP_SACK_NUM_PDU_LEN = 1
41+
};
3642
#endif /*__sctp_cmt__*/

net/sctp/outqueue.c

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,15 @@ static void sctp_check_transmitted(struct sctp_outq *q,
7373
struct sctp_transport *transport,
7474
union sctp_addr *saddr,
7575
struct sctp_sackhdr *sack,
76-
__u32 *highest_new_tsn);
76+
__u32 *highest_new_tsn,
77+
__u32 *lowest_new_tsn);
7778

7879
static void sctp_mark_missing(struct sctp_outq *q,
7980
struct list_head *transmitted_queue,
8081
struct sctp_transport *transport,
8182
__u32 highest_new_tsn,
83+
__u32 lowest_new_tsn,
84+
int num_pdu_acked,
8285
int count_of_newacks);
8386

8487
static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 sack_ctsn);
@@ -233,6 +236,57 @@ static inline int sctp_cmt_sfr_skip(struct sctp_transport *transport,
233236
return 1;
234237

235238
}
239+
240+
/** CMT-DAC algorithm step (4) */
241+
static inline int sctp_dac_missing(struct sctp_transport *transport,
242+
__u32 tsn, int num_pdu_acked,
243+
__u32 lowest_in_new, __u32 highest_in_new)
244+
{
245+
bool only_you;
246+
struct list_head *pos, *temp;
247+
struct sctp_transport *tmp_trxpt;
248+
int retval;
249+
BUG_ON(!transport);
250+
BUG_ON(num_pdu_acked < 0 || num_pdu_acked > 2);
251+
252+
only_you = true;
253+
list_for_each_safe(pos, temp, &transport->transports) {
254+
tmp_trxpt = list_entry(pos, struct sctp_transport, transports);
255+
if (tmp_trxpt->cmt_sfr.saw_newack && tmp_trxpt != transport) {
256+
only_you = false;
257+
break;
258+
}
259+
}
260+
/* DAC 4)
261+
* to determine whether missing report for a tsn tm should be ++
262+
* let dm be the destination to which tm was sent;
263+
* if (dm.saw_newack==true) and (dm.highest_in_sack_for_dest > tm)
264+
* then
265+
*/
266+
if(transport->cmt_sfr.saw_newack && TSN_lt(tsn, transport->cmt_sfr.hisfd)) {
267+
/* i) if any other desintations does not "see_new" */
268+
if(only_you) {// the acked packets are only sent through this destination
269+
if (lowest_in_new < tsn && tsn < highest_in_new)
270+
retval = 1;
271+
else
272+
retval = num_pdu_acked;
273+
}
274+
else // ii) others see new as well
275+
retval = 1;
276+
} else
277+
retval = 0;
278+
279+
cmt_debug("=======>retval=%d,tsn=0x%x, only_you=%d, lowest=0x%x, highest=0x%x, pdu_num=%d\n",
280+
retval,
281+
tsn,
282+
only_you,
283+
lowest_in_new,
284+
highest_in_new,
285+
num_pdu_acked
286+
);
287+
return retval;
288+
}
289+
236290
/* Initialize an existing sctp_outq. This does the boring stuff.
237291
* You still need to define handlers if you really want to DO
238292
* something with this structure...
@@ -1220,14 +1274,15 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
12201274
struct list_head *lchunk, *transport_list, *temp;
12211275
sctp_sack_variable_t *frags = sack->variable;
12221276
__u32 sack_ctsn, ctsn, tsn;
1223-
__u32 highest_tsn, highest_new_tsn;
1277+
__u32 highest_tsn, highest_new_tsn, lowest_new_tsn;
12241278
__u32 sack_a_rwnd;
12251279
char *to_console;
12261280
unsigned int outstanding;
12271281
struct sctp_transport *primary = asoc->peer.primary_path;
12281282
int count_of_newacks = 0;
12291283
int gap_ack_blocks;
12301284
u8 accum_moved = 0;
1285+
int num_pdu_acked;
12311286

12321287
/* Grab the association's destination address list. */
12331288
transport_list = &asoc->peer.transport_addr_list;
@@ -1256,6 +1311,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
12561311
sack_ctsn = ntohl(sack->cum_tsn_ack);
12571312
gap_ack_blocks = ntohs(sack->num_gap_ack_blocks);
12581313
asoc->stats.gapcnt += gap_ack_blocks;
1314+
1315+
/*For DAC - check if this SACK is for 2 the consecutive Data Chunks */
1316+
num_pdu_acked =
1317+
(chunk->chunk_hdr->flags&(1 << SCTP_SACK_NUM_PDU_BEG))? 2: 1;
12591318
/*
12601319
* SFR-CACC algorithm:
12611320
* On receipt of a SACK the sender SHOULD execute the
@@ -1320,6 +1379,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
13201379
if (TSN_lt(asoc->highest_sacked, highest_tsn))
13211380
asoc->highest_sacked = highest_tsn;
13221381

1382+
lowest_new_tsn = asoc->next_tsn;
13231383
highest_new_tsn = sack_ctsn;
13241384

13251385
/* CMT-CUC (2)
@@ -1355,7 +1415,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
13551415
/* Run through the retransmit queue. Credit bytes received
13561416
* and free those chunks that we can.
13571417
*/
1358-
sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn);
1418+
sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn, &lowest_new_tsn);
13591419

13601420
/* Run through the transmitted queue.
13611421
* Credit bytes received and free those chunks which we can.
@@ -1365,7 +1425,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
13651425
list_for_each_entry(transport, transport_list, transports) {
13661426
sctp_check_transmitted(q, &transport->transmitted,
13671427
transport, &chunk->source, sack,
1368-
&highest_new_tsn);
1428+
&highest_new_tsn, &lowest_new_tsn);
13691429
/*
13701430
* SFR-CACC algorithm:
13711431
* C) Let count_of_newacks be the number of
@@ -1391,8 +1451,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
13911451
highest_new_tsn = highest_tsn;
13921452

13931453
list_for_each_entry(transport, transport_list, transports)
1394-
sctp_mark_missing(q, &transport->transmitted, transport,
1395-
highest_new_tsn, count_of_newacks);
1454+
sctp_mark_missing(q, &transport->transmitted,
1455+
transport, highest_new_tsn,
1456+
lowest_new_tsn, num_pdu_acked,
1457+
count_of_newacks);
13961458
}
13971459

13981460
/* Update unack_data field in the assoc. */
@@ -1477,7 +1539,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
14771539
struct sctp_transport *transport,
14781540
union sctp_addr *saddr,
14791541
struct sctp_sackhdr *sack,
1480-
__u32 *highest_new_tsn_in_sack)
1542+
__u32 *highest_new_tsn_in_sack,
1543+
__u32 *lowest_new_tsn_in_sack)
14811544
{
14821545
struct list_head *lchunk;
14831546
struct sctp_chunk *tchunk;
@@ -1550,6 +1613,9 @@ static void sctp_check_transmitted(struct sctp_outq *q,
15501613
* while DATA was outstanding).
15511614
*/
15521615
if (!tchunk->tsn_gap_acked) {
1616+
// Find the lowest & highest respective
1617+
if (TSN_lt(tsn, *lowest_new_tsn_in_sack))
1618+
*lowest_new_tsn_in_sack = tsn;
15531619
if (TSN_lt(*highest_new_tsn_in_sack, tsn))
15541620
*highest_new_tsn_in_sack = tsn;
15551621
bytes_acked += sctp_data_size(tchunk);
@@ -1811,13 +1877,16 @@ static void sctp_mark_missing(struct sctp_outq *q,
18111877
struct list_head *transmitted_queue,
18121878
struct sctp_transport *transport,
18131879
__u32 highest_new_tsn_in_sack,
1880+
__u32 lowest_new_tsn_in_sack,
1881+
int num_pdu_acked,
18141882
int count_of_newacks)
18151883
{
18161884
struct sctp_chunk *chunk;
18171885
__u32 tsn;
18181886
char do_fast_retransmit = 0;
18191887
struct sctp_association *asoc = q->asoc;
18201888
struct sctp_transport *primary = asoc->peer.primary_path;
1889+
int missing_inc = 1;
18211890

18221891
list_for_each_entry(chunk, transmitted_queue, transmitted_list) {
18231892

@@ -1839,13 +1908,19 @@ static void sctp_mark_missing(struct sctp_outq *q,
18391908
*/
18401909
bool cacc = sctp_cacc_skip(primary, chunk->transport, count_of_newacks, tsn);
18411910
/*Apply CMT-SFR*/
1842-
bool sfr = sctp_cmt_sfr_skip(chunk->transport, tsn);
1843-
// bool sfr = false;
1911+
// bool sfr = sctp_cmt_sfr_skip(chunk->transport, tsn);
1912+
bool sfr = false;
18441913
if(sfr)
18451914
cmt_debug("==>sfr works!\n");
18461915
if (!transport || !(cacc || sfr)) {
1847-
chunk->tsn_missing_report++;
1848-
1916+
missing_inc = sctp_dac_missing(transport,
1917+
tsn, num_pdu_acked,
1918+
lowest_new_tsn_in_sack,
1919+
highest_new_tsn_in_sack);
1920+
chunk->tsn_missing_report+= missing_inc;
1921+
1922+
if (missing_inc >= 2)
1923+
cmt_debug("--->DAC works!\n");
18491924
pr_debug("%s: tsn:0x%x missing counter:%d\n",
18501925
__func__, tsn, chunk->tsn_missing_report);
18511926

net/sctp/sm_make_chunk.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include <linux/random.h> /* for get_random_bytes */
6868
#include <net/sctp/sctp.h>
6969
#include <net/sctp/sm.h>
70+
#include <net/sctp/cmt.h>
7071

7172
static struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
7273
__u8 type, __u8 flags, int paylen);
@@ -823,6 +824,12 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
823824
trans->sack_generation = 0;
824825
aptr->peer.sack_generation = 1;
825826
}
827+
828+
/* If this sack is for the 2nd data chunk. Refer to RFC2581*/
829+
if(asoc->peer.sack_cnt >= 2) {// This is ugly!
830+
retval->chunk_hdr->flags |= (1 << SCTP_SACK_NUM_PDU_BEG);
831+
}
832+
826833
nodata:
827834
return retval;
828835
}

net/sctp/sm_sideeffect.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
188188
*
189189
* [This is actually not mentioned in Section 6, but we
190190
* implement it here anyway. --piggy]
191+
*
192+
* [This check should be removed as unordered delivery is common to
193+
* CMT --chang]
191194
*/
192195
if (max_tsn_seen != ctsn)
193196
asoc->peer.sack_needed = 1;

net/sctp/sm_statefuns.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include <linux/skbuff.h>
6565
#include <net/sctp/sctp.h>
6666
#include <net/sctp/sm.h>
67+
#include <net/sctp/cmt.h>
6768
#include <net/sctp/structs.h>
6869

6970
static struct sctp_packet *sctp_abort_pkt_new(struct net *net,
@@ -3171,6 +3172,9 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net,
31713172
chunk->subh.sack_hdr = sackh;
31723173
ctsn = ntohl(sackh->cum_tsn_ack);
31733174

3175+
if(chunk->chunk_hdr->flags & (1 << SCTP_SACK_NUM_PDU_BEG))
3176+
cmt_debug("==========>bit set!\n");
3177+
31743178
/* i) If Cumulative TSN Ack is less than the Cumulative TSN
31753179
* Ack Point, then drop the SACK. Since Cumulative TSN
31763180
* Ack is monotonically increasing, a SACK whose

0 commit comments

Comments
 (0)