22
22
#include <net/sock.h>
23
23
24
24
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
+ }
25
66
26
67
int dccp_insert_option_ackvec (struct sock * sk , struct sk_buff * skb )
27
68
{
@@ -35,26 +76,21 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
35
76
struct timeval now ;
36
77
u32 elapsed_time ;
37
78
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 ;
38
87
39
88
dccp_timestamp (sk , & now );
40
89
elapsed_time = timeval_delta (& now , & av -> dccpav_time ) / 10 ;
41
90
42
91
if (elapsed_time != 0 )
43
92
dccp_insert_option_elapsed_time (sk , skb , elapsed_time );
44
93
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
-
58
94
DCCP_SKB_CB (skb )-> dccpd_opt_len += len ;
59
95
60
96
to = skb_push (skb , len );
@@ -65,8 +101,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
65
101
from = av -> dccpav_buf + av -> dccpav_buf_head ;
66
102
67
103
/* 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 ;
70
106
71
107
memcpy (to , from , tailsize );
72
108
to += tailsize ;
@@ -83,21 +119,21 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
83
119
* sequence number it used for the ack packet; ack_ptr will equal
84
120
* buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
85
121
* equal buf_nonce.
86
- *
87
- * This implemention uses just one ack record for now.
88
122
*/
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 );
94
130
95
131
dccp_pr_debug ("%sACK Vector 0, len=%d, ack_seqno=%llu, "
96
132
"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 ;
101
137
}
102
138
103
139
struct dccp_ackvec * dccp_ackvec_alloc (const gfp_t priority )
@@ -107,20 +143,23 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
107
143
if (av != NULL ) {
108
144
av -> dccpav_buf_head =
109
145
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 ;
112
147
av -> dccpav_buf_nonce = av -> dccpav_buf_nonce = 0 ;
113
148
av -> dccpav_ack_ptr = 0 ;
114
149
av -> dccpav_time .tv_sec = 0 ;
115
150
av -> dccpav_time .tv_usec = 0 ;
116
151
av -> dccpav_sent_len = av -> dccpav_vec_len = 0 ;
152
+ INIT_LIST_HEAD (& av -> dccpav_records );
117
153
}
118
154
119
155
return av ;
120
156
}
121
157
122
158
void dccp_ackvec_free (struct dccp_ackvec * av )
123
159
{
160
+ if (unlikely (av == NULL ))
161
+ return ;
162
+ WARN_ON (!list_empty (& av -> dccpav_records ));
124
163
kmem_cache_free (dccp_ackvec_slab , av );
125
164
}
126
165
@@ -299,44 +338,50 @@ void dccp_ackvec_print(const struct dccp_ackvec *av)
299
338
}
300
339
#endif
301
340
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 )
303
343
{
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
+ }
318
358
}
319
359
320
360
void dccp_ackvec_check_rcv_ackno (struct dccp_ackvec * av , struct sock * sk ,
321
361
const u64 ackno )
322
362
{
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 ;
326
364
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 ) {
328
372
#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: " ;
332
376
#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
+ }
340
385
}
341
386
}
342
387
@@ -346,43 +391,41 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
346
391
const unsigned char * vector )
347
392
{
348
393
unsigned char i ;
394
+ struct dccp_ackvec_record * avr ;
349
395
350
396
/* 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 ) )
352
398
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"); */
369
399
370
400
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 );
371
408
while (i -- ) {
372
409
const u8 rl = * vector & DCCP_ACKVEC_LEN_MASK ;
373
410
u64 ackno_end_rl ;
374
411
375
412
dccp_set_seqno (& ackno_end_rl , ackno - rl );
376
413
377
414
/*
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.
380
417
*/
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 )) {
382
427
const u8 state = (* vector &
383
428
DCCP_ACKVEC_STATE_MASK ) >> 6 ;
384
- /* dccp_pr_debug_cat("yes\n"); */
385
-
386
429
if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED ) {
387
430
#ifdef CONFIG_IP_DCCP_DEBUG
388
431
struct dccp_sock * dp = dccp_sk (sk );
@@ -395,19 +438,16 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
395
438
"ACKED!\n" ,
396
439
debug_prefix , len ,
397
440
(unsigned long long )
398
- av -> dccpav_ack_seqno ,
441
+ avr -> dccpavr_ack_seqno ,
399
442
(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 );
402
445
}
403
446
/*
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 .
406
449
*/
407
- av -> dccpav_ack_seqno = DCCP_MAX_SEQNO + 1 ;
408
- break ;
409
450
}
410
- /* dccp_pr_debug_cat("no\n"); */
411
451
412
452
dccp_set_seqno (& ackno , ackno_end_rl - 1 );
413
453
++ vector ;
@@ -428,19 +468,31 @@ int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
428
468
}
429
469
430
470
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" ;
432
472
433
473
int __init dccp_ackvec_init (void )
434
474
{
435
475
dccp_ackvec_slab = kmem_cache_create ("dccp_ackvec" ,
436
476
sizeof (struct dccp_ackvec ), 0 ,
437
477
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 ;
442
487
443
488
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 ;
444
496
}
445
497
446
498
void dccp_ackvec_exit (void )
@@ -449,4 +501,8 @@ void dccp_ackvec_exit(void)
449
501
kmem_cache_destroy (dccp_ackvec_slab );
450
502
dccp_ackvec_slab = NULL ;
451
503
}
504
+ if (dccp_ackvec_record_slab != NULL ) {
505
+ kmem_cache_destroy (dccp_ackvec_record_slab );
506
+ dccp_ackvec_record_slab = NULL ;
507
+ }
452
508
}
0 commit comments