Skip to content

Commit 02bcf28

Browse files
Andrea Bittaudavem330
authored andcommitted
[DCCP] ackvec: Introduce ack vector records
Based on a patch by Andrea Bittau. Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk> Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e229c2f commit 02bcf28

File tree

2 files changed

+173
-98
lines changed

2 files changed

+173
-98
lines changed

net/dccp/ackvec.c

Lines changed: 148 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,47 @@
2222
#include <net/sock.h>
2323

2424
static kmem_cache_t *dccp_ackvec_slab;
25+
static kmem_cache_t *dccp_ackvec_record_slab;
26+
27+
static struct dccp_ackvec_record *dccp_ackvec_record_new(void)
28+
{
29+
struct dccp_ackvec_record *avr =
30+
kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC);
31+
32+
if (avr != NULL)
33+
INIT_LIST_HEAD(&avr->dccpavr_node);
34+
35+
return avr;
36+
}
37+
38+
static void dccp_ackvec_record_delete(struct dccp_ackvec_record *avr)
39+
{
40+
if (unlikely(avr == NULL))
41+
return;
42+
/* Check if deleting a linked record */
43+
WARN_ON(!list_empty(&avr->dccpavr_node));
44+
kmem_cache_free(dccp_ackvec_record_slab, avr);
45+
}
46+
47+
static void dccp_ackvec_insert_avr(struct dccp_ackvec *av,
48+
struct dccp_ackvec_record *avr)
49+
{
50+
/*
51+
* AVRs are sorted by seqno. Since we are sending them in order, we
52+
* just add the AVR at the head of the list.
53+
* -sorbo.
54+
*/
55+
if (!list_empty(&av->dccpav_records)) {
56+
const struct dccp_ackvec_record *head =
57+
list_entry(av->dccpav_records.next,
58+
struct dccp_ackvec_record,
59+
dccpavr_node);
60+
BUG_ON(before48(avr->dccpavr_ack_seqno,
61+
head->dccpavr_ack_seqno));
62+
}
63+
64+
list_add(&avr->dccpavr_node, &av->dccpav_records);
65+
}
2566

2667
int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
2768
{
@@ -35,26 +76,21 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
3576
struct timeval now;
3677
u32 elapsed_time;
3778
unsigned char *to, *from;
79+
struct dccp_ackvec_record *avr;
80+
81+
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
82+
return -1;
83+
84+
avr = dccp_ackvec_record_new();
85+
if (avr == NULL)
86+
return -1;
3887

3988
dccp_timestamp(sk, &now);
4089
elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
4190

4291
if (elapsed_time != 0)
4392
dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
4493

45-
if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
46-
return -1;
47-
48-
/*
49-
* XXX: now we have just one ack vector sent record, so
50-
* we have to wait for it to be cleared.
51-
*
52-
* Of course this is not acceptable, but this is just for
53-
* basic testing now.
54-
*/
55-
if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1)
56-
return -1;
57-
5894
DCCP_SKB_CB(skb)->dccpd_opt_len += len;
5995

6096
to = skb_push(skb, len);
@@ -65,8 +101,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
65101
from = av->dccpav_buf + av->dccpav_buf_head;
66102

67103
/* Check if buf_head wraps */
68-
if ((int)av->dccpav_buf_head + len > av->dccpav_vec_len) {
69-
const u32 tailsize = av->dccpav_vec_len - av->dccpav_buf_head;
104+
if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) {
105+
const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head;
70106

71107
memcpy(to, from, tailsize);
72108
to += tailsize;
@@ -83,21 +119,21 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
83119
* sequence number it used for the ack packet; ack_ptr will equal
84120
* buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
85121
* equal buf_nonce.
86-
*
87-
* This implemention uses just one ack record for now.
88122
*/
89-
av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
90-
av->dccpav_ack_ptr = av->dccpav_buf_head;
91-
av->dccpav_ack_ackno = av->dccpav_buf_ackno;
92-
av->dccpav_ack_nonce = av->dccpav_buf_nonce;
93-
av->dccpav_sent_len = av->dccpav_vec_len;
123+
avr->dccpavr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
124+
avr->dccpavr_ack_ptr = av->dccpav_buf_head;
125+
avr->dccpavr_ack_ackno = av->dccpav_buf_ackno;
126+
avr->dccpavr_ack_nonce = av->dccpav_buf_nonce;
127+
avr->dccpavr_sent_len = av->dccpav_vec_len;
128+
129+
dccp_ackvec_insert_avr(av, avr);
94130

95131
dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
96132
"ack_ackno=%llu\n",
97-
debug_prefix, av->dccpav_sent_len,
98-
(unsigned long long)av->dccpav_ack_seqno,
99-
(unsigned long long)av->dccpav_ack_ackno);
100-
return -1;
133+
debug_prefix, avr->dccpavr_sent_len,
134+
(unsigned long long)avr->dccpavr_ack_seqno,
135+
(unsigned long long)avr->dccpavr_ack_ackno);
136+
return 0;
101137
}
102138

103139
struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
@@ -107,20 +143,23 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
107143
if (av != NULL) {
108144
av->dccpav_buf_head =
109145
av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
110-
av->dccpav_buf_ackno =
111-
av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU;
146+
av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
112147
av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
113148
av->dccpav_ack_ptr = 0;
114149
av->dccpav_time.tv_sec = 0;
115150
av->dccpav_time.tv_usec = 0;
116151
av->dccpav_sent_len = av->dccpav_vec_len = 0;
152+
INIT_LIST_HEAD(&av->dccpav_records);
117153
}
118154

119155
return av;
120156
}
121157

122158
void dccp_ackvec_free(struct dccp_ackvec *av)
123159
{
160+
if (unlikely(av == NULL))
161+
return;
162+
WARN_ON(!list_empty(&av->dccpav_records));
124163
kmem_cache_free(dccp_ackvec_slab, av);
125164
}
126165

@@ -299,44 +338,50 @@ void dccp_ackvec_print(const struct dccp_ackvec *av)
299338
}
300339
#endif
301340

302-
static void dccp_ackvec_throw_away_ack_record(struct dccp_ackvec *av)
341+
static void dccp_ackvec_throw_record(struct dccp_ackvec *av,
342+
struct dccp_ackvec_record *avr)
303343
{
304-
/*
305-
* As we're keeping track of the ack vector size (dccpav_vec_len) and
306-
* the sent ack vector size (dccpav_sent_len) we don't need
307-
* dccpav_buf_tail at all, but keep this code here as in the future
308-
* we'll implement a vector of ack records, as suggested in
309-
* draft-ietf-dccp-spec-11.txt Appendix A. -acme
310-
*/
311-
#if 0
312-
u32 new_buf_tail = av->dccpav_ack_ptr + 1;
313-
if (new_buf_tail >= av->dccpav_vec_len)
314-
new_buf_tail -= av->dccpav_vec_len;
315-
av->dccpav_buf_tail = new_buf_tail;
316-
#endif
317-
av->dccpav_vec_len -= av->dccpav_sent_len;
344+
struct dccp_ackvec_record *next;
345+
346+
av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1;
347+
if (av->dccpav_buf_tail == 0)
348+
av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
349+
350+
av->dccpav_vec_len -= avr->dccpavr_sent_len;
351+
352+
/* free records */
353+
list_for_each_entry_safe_from(avr, next, &av->dccpav_records,
354+
dccpavr_node) {
355+
list_del_init(&avr->dccpavr_node);
356+
dccp_ackvec_record_delete(avr);
357+
}
318358
}
319359

320360
void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
321361
const u64 ackno)
322362
{
323-
/* Check if we actually sent an ACK vector */
324-
if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
325-
return;
363+
struct dccp_ackvec_record *avr;
326364

327-
if (ackno == av->dccpav_ack_seqno) {
365+
/*
366+
* If we traverse backwards, it should be faster when we have large
367+
* windows. We will be receiving ACKs for stuff we sent a while back
368+
* -sorbo.
369+
*/
370+
list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) {
371+
if (ackno == avr->dccpavr_ack_seqno) {
328372
#ifdef CONFIG_IP_DCCP_DEBUG
329-
struct dccp_sock *dp = dccp_sk(sk);
330-
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
331-
"CLIENT rx ack: " : "server rx ack: ";
373+
struct dccp_sock *dp = dccp_sk(sk);
374+
const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
375+
"CLIENT rx ack: " : "server rx ack: ";
332376
#endif
333-
dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
334-
"ack_ackno=%llu, ACKED!\n",
335-
debug_prefix, 1,
336-
(unsigned long long)av->dccpav_ack_seqno,
337-
(unsigned long long)av->dccpav_ack_ackno);
338-
dccp_ackvec_throw_away_ack_record(av);
339-
av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
377+
dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
378+
"ack_ackno=%llu, ACKED!\n",
379+
debug_prefix, 1,
380+
(unsigned long long)avr->dccpavr_ack_seqno,
381+
(unsigned long long)avr->dccpavr_ack_ackno);
382+
dccp_ackvec_throw_record(av, avr);
383+
break;
384+
}
340385
}
341386
}
342387

@@ -346,43 +391,41 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
346391
const unsigned char *vector)
347392
{
348393
unsigned char i;
394+
struct dccp_ackvec_record *avr;
349395

350396
/* Check if we actually sent an ACK vector */
351-
if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
397+
if (list_empty(&av->dccpav_records))
352398
return;
353-
/*
354-
* We're in the receiver half connection, so if the received an ACK
355-
* vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're
356-
* not interested.
357-
*
358-
* Extra explanation with example:
359-
*
360-
* if we received an ACK vector with ackno 50, it can only be acking
361-
* 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
362-
*/
363-
/* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */
364-
if (before48(ackno, av->dccpav_ack_seqno)) {
365-
/* dccp_pr_debug_cat("yes\n"); */
366-
return;
367-
}
368-
/* dccp_pr_debug_cat("no\n"); */
369399

370400
i = len;
401+
/*
402+
* XXX
403+
* I think it might be more efficient to work backwards. See comment on
404+
* rcv_ackno. -sorbo.
405+
*/
406+
avr = list_entry(av->dccpav_records.next, struct dccp_ackvec_record,
407+
dccpavr_node);
371408
while (i--) {
372409
const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
373410
u64 ackno_end_rl;
374411

375412
dccp_set_seqno(&ackno_end_rl, ackno - rl);
376413

377414
/*
378-
* dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl,
379-
* av->dccpav_ack_seqno, ackno);
415+
* If our AVR sequence number is greater than the ack, go
416+
* forward in the AVR list until it is not so.
380417
*/
381-
if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) {
418+
list_for_each_entry_from(avr, &av->dccpav_records,
419+
dccpavr_node) {
420+
if (!after48(avr->dccpavr_ack_seqno, ackno))
421+
goto found;
422+
}
423+
/* End of the dccpav_records list, not found, exit */
424+
break;
425+
found:
426+
if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
382427
const u8 state = (*vector &
383428
DCCP_ACKVEC_STATE_MASK) >> 6;
384-
/* dccp_pr_debug_cat("yes\n"); */
385-
386429
if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
387430
#ifdef CONFIG_IP_DCCP_DEBUG
388431
struct dccp_sock *dp = dccp_sk(sk);
@@ -395,19 +438,16 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
395438
"ACKED!\n",
396439
debug_prefix, len,
397440
(unsigned long long)
398-
av->dccpav_ack_seqno,
441+
avr->dccpavr_ack_seqno,
399442
(unsigned long long)
400-
av->dccpav_ack_ackno);
401-
dccp_ackvec_throw_away_ack_record(av);
443+
avr->dccpavr_ack_ackno);
444+
dccp_ackvec_throw_record(av, avr);
402445
}
403446
/*
404-
* If dccpav_ack_seqno was not received, no problem
405-
* we'll send another ACK vector.
447+
* If it wasn't received, continue scanning... we might
448+
* find another one.
406449
*/
407-
av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
408-
break;
409450
}
410-
/* dccp_pr_debug_cat("no\n"); */
411451

412452
dccp_set_seqno(&ackno, ackno_end_rl - 1);
413453
++vector;
@@ -428,19 +468,31 @@ int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
428468
}
429469

430470
static char dccp_ackvec_slab_msg[] __initdata =
431-
KERN_CRIT "DCCP: Unable to create ack vectors slab cache\n";
471+
KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n";
432472

433473
int __init dccp_ackvec_init(void)
434474
{
435475
dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
436476
sizeof(struct dccp_ackvec), 0,
437477
SLAB_HWCACHE_ALIGN, NULL, NULL);
438-
if (dccp_ackvec_slab == NULL) {
439-
printk(dccp_ackvec_slab_msg);
440-
return -ENOBUFS;
441-
}
478+
if (dccp_ackvec_slab == NULL)
479+
goto out_err;
480+
481+
dccp_ackvec_record_slab =
482+
kmem_cache_create("dccp_ackvec_record",
483+
sizeof(struct dccp_ackvec_record),
484+
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
485+
if (dccp_ackvec_record_slab == NULL)
486+
goto out_destroy_slab;
442487

443488
return 0;
489+
490+
out_destroy_slab:
491+
kmem_cache_destroy(dccp_ackvec_slab);
492+
dccp_ackvec_slab = NULL;
493+
out_err:
494+
printk(dccp_ackvec_slab_msg);
495+
return -ENOBUFS;
444496
}
445497

446498
void dccp_ackvec_exit(void)
@@ -449,4 +501,8 @@ void dccp_ackvec_exit(void)
449501
kmem_cache_destroy(dccp_ackvec_slab);
450502
dccp_ackvec_slab = NULL;
451503
}
504+
if (dccp_ackvec_record_slab != NULL) {
505+
kmem_cache_destroy(dccp_ackvec_record_slab);
506+
dccp_ackvec_record_slab = NULL;
507+
}
452508
}

0 commit comments

Comments
 (0)