aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ackvec.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ackvec.c')
-rw-r--r--net/dccp/ackvec.c296
1 files changed, 194 insertions, 102 deletions
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index 2c77dafbd091..b5981e5f6b00 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -13,36 +13,83 @@
13#include "dccp.h" 13#include "dccp.h"
14 14
15#include <linux/dccp.h> 15#include <linux/dccp.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/kernel.h>
16#include <linux/skbuff.h> 19#include <linux/skbuff.h>
20#include <linux/slab.h>
17 21
18#include <net/sock.h> 22#include <net/sock.h>
19 23
24static kmem_cache_t *dccp_ackvec_slab;
25static kmem_cache_t *dccp_ackvec_record_slab;
26
27static 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
38static 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
47static 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}
66
20int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) 67int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
21{ 68{
22 struct dccp_sock *dp = dccp_sk(sk); 69 struct dccp_sock *dp = dccp_sk(sk);
70#ifdef CONFIG_IP_DCCP_DEBUG
71 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
72 "CLIENT tx: " : "server tx: ";
73#endif
23 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; 74 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
24 int len = av->dccpav_vec_len + 2; 75 int len = av->dccpav_vec_len + 2;
25 struct timeval now; 76 struct timeval now;
26 u32 elapsed_time; 77 u32 elapsed_time;
27 unsigned char *to, *from; 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;
28 83
29 dccp_timestamp(sk, &now); 84 dccp_timestamp(sk, &now);
30 elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; 85 elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10;
31 86
32 if (elapsed_time != 0) 87 if (elapsed_time != 0 &&
33 dccp_insert_option_elapsed_time(sk, skb, elapsed_time); 88 dccp_insert_option_elapsed_time(sk, skb, elapsed_time))
34
35 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
36 return -1; 89 return -1;
37 90
38 /* 91 avr = dccp_ackvec_record_new();
39 * XXX: now we have just one ack vector sent record, so 92 if (avr == NULL)
40 * we have to wait for it to be cleared.
41 *
42 * Of course this is not acceptable, but this is just for
43 * basic testing now.
44 */
45 if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1)
46 return -1; 93 return -1;
47 94
48 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 95 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
@@ -55,8 +102,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
55 from = av->dccpav_buf + av->dccpav_buf_head; 102 from = av->dccpav_buf + av->dccpav_buf_head;
56 103
57 /* Check if buf_head wraps */ 104 /* Check if buf_head wraps */
58 if ((int)av->dccpav_buf_head + len > av->dccpav_vec_len) { 105 if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) {
59 const u32 tailsize = av->dccpav_vec_len - av->dccpav_buf_head; 106 const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head;
60 107
61 memcpy(to, from, tailsize); 108 memcpy(to, from, tailsize);
62 to += tailsize; 109 to += tailsize;
@@ -73,45 +120,37 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
73 * sequence number it used for the ack packet; ack_ptr will equal 120 * sequence number it used for the ack packet; ack_ptr will equal
74 * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will 121 * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will
75 * equal buf_nonce. 122 * equal buf_nonce.
76 *
77 * This implemention uses just one ack record for now.
78 */ 123 */
79 av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; 124 avr->dccpavr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
80 av->dccpav_ack_ptr = av->dccpav_buf_head; 125 avr->dccpavr_ack_ptr = av->dccpav_buf_head;
81 av->dccpav_ack_ackno = av->dccpav_buf_ackno; 126 avr->dccpavr_ack_ackno = av->dccpav_buf_ackno;
82 av->dccpav_ack_nonce = av->dccpav_buf_nonce; 127 avr->dccpavr_ack_nonce = av->dccpav_buf_nonce;
83 av->dccpav_sent_len = av->dccpav_vec_len; 128 avr->dccpavr_sent_len = av->dccpav_vec_len;
129
130 dccp_ackvec_insert_avr(av, avr);
84 131
85 dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " 132 dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, "
86 "ack_ackno=%llu\n", 133 "ack_ackno=%llu\n",
87 debug_prefix, av->dccpav_sent_len, 134 debug_prefix, avr->dccpavr_sent_len,
88 (unsigned long long)av->dccpav_ack_seqno, 135 (unsigned long long)avr->dccpavr_ack_seqno,
89 (unsigned long long)av->dccpav_ack_ackno); 136 (unsigned long long)avr->dccpavr_ack_ackno);
90 return -1; 137 return 0;
91} 138}
92 139
93struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, 140struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
94 const gfp_t priority)
95{ 141{
96 struct dccp_ackvec *av; 142 struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority);
97
98 BUG_ON(len == 0);
99 143
100 if (len > DCCP_MAX_ACKVEC_LEN)
101 return NULL;
102
103 av = kmalloc(sizeof(*av) + len, priority);
104 if (av != NULL) { 144 if (av != NULL) {
105 av->dccpav_buf_len = len;
106 av->dccpav_buf_head = 145 av->dccpav_buf_head =
107 av->dccpav_buf_tail = av->dccpav_buf_len - 1; 146 av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
108 av->dccpav_buf_ackno = 147 av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
109 av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU;
110 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; 148 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
111 av->dccpav_ack_ptr = 0; 149 av->dccpav_ack_ptr = 0;
112 av->dccpav_time.tv_sec = 0; 150 av->dccpav_time.tv_sec = 0;
113 av->dccpav_time.tv_usec = 0; 151 av->dccpav_time.tv_usec = 0;
114 av->dccpav_sent_len = av->dccpav_vec_len = 0; 152 av->dccpav_sent_len = av->dccpav_vec_len = 0;
153 INIT_LIST_HEAD(&av->dccpav_records);
115 } 154 }
116 155
117 return av; 156 return av;
@@ -119,7 +158,20 @@ struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len,
119 158
120void dccp_ackvec_free(struct dccp_ackvec *av) 159void dccp_ackvec_free(struct dccp_ackvec *av)
121{ 160{
122 kfree(av); 161 if (unlikely(av == NULL))
162 return;
163
164 if (!list_empty(&av->dccpav_records)) {
165 struct dccp_ackvec_record *avr, *next;
166
167 list_for_each_entry_safe(avr, next, &av->dccpav_records,
168 dccpavr_node) {
169 list_del_init(&avr->dccpavr_node);
170 dccp_ackvec_record_delete(avr);
171 }
172 }
173
174 kmem_cache_free(dccp_ackvec_slab, av);
123} 175}
124 176
125static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, 177static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
@@ -146,7 +198,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
146 unsigned int gap; 198 unsigned int gap;
147 long new_head; 199 long new_head;
148 200
149 if (av->dccpav_vec_len + packets > av->dccpav_buf_len) 201 if (av->dccpav_vec_len + packets > DCCP_MAX_ACKVEC_LEN)
150 return -ENOBUFS; 202 return -ENOBUFS;
151 203
152 gap = packets - 1; 204 gap = packets - 1;
@@ -158,7 +210,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
158 gap + new_head + 1); 210 gap + new_head + 1);
159 gap = -new_head; 211 gap = -new_head;
160 } 212 }
161 new_head += av->dccpav_buf_len; 213 new_head += DCCP_MAX_ACKVEC_LEN;
162 } 214 }
163 215
164 av->dccpav_buf_head = new_head; 216 av->dccpav_buf_head = new_head;
@@ -251,7 +303,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
251 goto out_duplicate; 303 goto out_duplicate;
252 304
253 delta -= len + 1; 305 delta -= len + 1;
254 if (++index == av->dccpav_buf_len) 306 if (++index == DCCP_MAX_ACKVEC_LEN)
255 index = 0; 307 index = 0;
256 } 308 }
257 } 309 }
@@ -259,7 +311,6 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
259 av->dccpav_buf_ackno = ackno; 311 av->dccpav_buf_ackno = ackno;
260 dccp_timestamp(sk, &av->dccpav_time); 312 dccp_timestamp(sk, &av->dccpav_time);
261out: 313out:
262 dccp_pr_debug("");
263 return 0; 314 return 0;
264 315
265out_duplicate: 316out_duplicate:
@@ -297,44 +348,50 @@ void dccp_ackvec_print(const struct dccp_ackvec *av)
297} 348}
298#endif 349#endif
299 350
300static void dccp_ackvec_throw_away_ack_record(struct dccp_ackvec *av) 351static void dccp_ackvec_throw_record(struct dccp_ackvec *av,
352 struct dccp_ackvec_record *avr)
301{ 353{
302 /* 354 struct dccp_ackvec_record *next;
303 * As we're keeping track of the ack vector size (dccpav_vec_len) and 355
304 * the sent ack vector size (dccpav_sent_len) we don't need 356 av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1;
305 * dccpav_buf_tail at all, but keep this code here as in the future 357 if (av->dccpav_buf_tail == 0)
306 * we'll implement a vector of ack records, as suggested in 358 av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1;
307 * draft-ietf-dccp-spec-11.txt Appendix A. -acme 359
308 */ 360 av->dccpav_vec_len -= avr->dccpavr_sent_len;
309#if 0 361
310 u32 new_buf_tail = av->dccpav_ack_ptr + 1; 362 /* free records */
311 if (new_buf_tail >= av->dccpav_vec_len) 363 list_for_each_entry_safe_from(avr, next, &av->dccpav_records,
312 new_buf_tail -= av->dccpav_vec_len; 364 dccpavr_node) {
313 av->dccpav_buf_tail = new_buf_tail; 365 list_del_init(&avr->dccpavr_node);
314#endif 366 dccp_ackvec_record_delete(avr);
315 av->dccpav_vec_len -= av->dccpav_sent_len; 367 }
316} 368}
317 369
318void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, 370void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
319 const u64 ackno) 371 const u64 ackno)
320{ 372{
321 /* Check if we actually sent an ACK vector */ 373 struct dccp_ackvec_record *avr;
322 if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1)
323 return;
324 374
325 if (ackno == av->dccpav_ack_seqno) { 375 /*
376 * If we traverse backwards, it should be faster when we have large
377 * windows. We will be receiving ACKs for stuff we sent a while back
378 * -sorbo.
379 */
380 list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) {
381 if (ackno == avr->dccpavr_ack_seqno) {
326#ifdef CONFIG_IP_DCCP_DEBUG 382#ifdef CONFIG_IP_DCCP_DEBUG
327 struct dccp_sock *dp = dccp_sk(sk); 383 struct dccp_sock *dp = dccp_sk(sk);
328 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? 384 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
329 "CLIENT rx ack: " : "server rx ack: "; 385 "CLIENT rx ack: " : "server rx ack: ";
330#endif 386#endif
331 dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " 387 dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
332 "ack_ackno=%llu, ACKED!\n", 388 "ack_ackno=%llu, ACKED!\n",
333 debug_prefix, 1, 389 debug_prefix, 1,
334 (unsigned long long)av->dccpav_ack_seqno, 390 (unsigned long long)avr->dccpavr_ack_seqno,
335 (unsigned long long)av->dccpav_ack_ackno); 391 (unsigned long long)avr->dccpavr_ack_ackno);
336 dccp_ackvec_throw_away_ack_record(av); 392 dccp_ackvec_throw_record(av, avr);
337 av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; 393 break;
394 }
338 } 395 }
339} 396}
340 397
@@ -344,28 +401,20 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
344 const unsigned char *vector) 401 const unsigned char *vector)
345{ 402{
346 unsigned char i; 403 unsigned char i;
404 struct dccp_ackvec_record *avr;
347 405
348 /* Check if we actually sent an ACK vector */ 406 /* Check if we actually sent an ACK vector */
349 if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) 407 if (list_empty(&av->dccpav_records))
350 return;
351 /*
352 * We're in the receiver half connection, so if the received an ACK
353 * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're
354 * not interested.
355 *
356 * Extra explanation with example:
357 *
358 * if we received an ACK vector with ackno 50, it can only be acking
359 * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
360 */
361 /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */
362 if (before48(ackno, av->dccpav_ack_seqno)) {
363 /* dccp_pr_debug_cat("yes\n"); */
364 return; 408 return;
365 }
366 /* dccp_pr_debug_cat("no\n"); */
367 409
368 i = len; 410 i = len;
411 /*
412 * XXX
413 * I think it might be more efficient to work backwards. See comment on
414 * rcv_ackno. -sorbo.
415 */
416 avr = list_entry(av->dccpav_records.next, struct dccp_ackvec_record,
417 dccpavr_node);
369 while (i--) { 418 while (i--) {
370 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; 419 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
371 u64 ackno_end_rl; 420 u64 ackno_end_rl;
@@ -373,14 +422,20 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
373 dccp_set_seqno(&ackno_end_rl, ackno - rl); 422 dccp_set_seqno(&ackno_end_rl, ackno - rl);
374 423
375 /* 424 /*
376 * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, 425 * If our AVR sequence number is greater than the ack, go
377 * av->dccpav_ack_seqno, ackno); 426 * forward in the AVR list until it is not so.
378 */ 427 */
379 if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) { 428 list_for_each_entry_from(avr, &av->dccpav_records,
429 dccpavr_node) {
430 if (!after48(avr->dccpavr_ack_seqno, ackno))
431 goto found;
432 }
433 /* End of the dccpav_records list, not found, exit */
434 break;
435found:
436 if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) {
380 const u8 state = (*vector & 437 const u8 state = (*vector &
381 DCCP_ACKVEC_STATE_MASK) >> 6; 438 DCCP_ACKVEC_STATE_MASK) >> 6;
382 /* dccp_pr_debug_cat("yes\n"); */
383
384 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { 439 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
385#ifdef CONFIG_IP_DCCP_DEBUG 440#ifdef CONFIG_IP_DCCP_DEBUG
386 struct dccp_sock *dp = dccp_sk(sk); 441 struct dccp_sock *dp = dccp_sk(sk);
@@ -393,19 +448,16 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
393 "ACKED!\n", 448 "ACKED!\n",
394 debug_prefix, len, 449 debug_prefix, len,
395 (unsigned long long) 450 (unsigned long long)
396 av->dccpav_ack_seqno, 451 avr->dccpavr_ack_seqno,
397 (unsigned long long) 452 (unsigned long long)
398 av->dccpav_ack_ackno); 453 avr->dccpavr_ack_ackno);
399 dccp_ackvec_throw_away_ack_record(av); 454 dccp_ackvec_throw_record(av, avr);
400 } 455 }
401 /* 456 /*
402 * If dccpav_ack_seqno was not received, no problem 457 * If it wasn't received, continue scanning... we might
403 * we'll send another ACK vector. 458 * find another one.
404 */ 459 */
405 av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
406 break;
407 } 460 }
408 /* dccp_pr_debug_cat("no\n"); */
409 461
410 dccp_set_seqno(&ackno, ackno_end_rl - 1); 462 dccp_set_seqno(&ackno, ackno_end_rl - 1);
411 ++vector; 463 ++vector;
@@ -424,3 +476,43 @@ int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
424 len, value); 476 len, value);
425 return 0; 477 return 0;
426} 478}
479
480static char dccp_ackvec_slab_msg[] __initdata =
481 KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n";
482
483int __init dccp_ackvec_init(void)
484{
485 dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
486 sizeof(struct dccp_ackvec), 0,
487 SLAB_HWCACHE_ALIGN, NULL, NULL);
488 if (dccp_ackvec_slab == NULL)
489 goto out_err;
490
491 dccp_ackvec_record_slab =
492 kmem_cache_create("dccp_ackvec_record",
493 sizeof(struct dccp_ackvec_record),
494 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
495 if (dccp_ackvec_record_slab == NULL)
496 goto out_destroy_slab;
497
498 return 0;
499
500out_destroy_slab:
501 kmem_cache_destroy(dccp_ackvec_slab);
502 dccp_ackvec_slab = NULL;
503out_err:
504 printk(dccp_ackvec_slab_msg);
505 return -ENOBUFS;
506}
507
508void dccp_ackvec_exit(void)
509{
510 if (dccp_ackvec_slab != NULL) {
511 kmem_cache_destroy(dccp_ackvec_slab);
512 dccp_ackvec_slab = NULL;
513 }
514 if (dccp_ackvec_record_slab != NULL) {
515 kmem_cache_destroy(dccp_ackvec_record_slab);
516 dccp_ackvec_record_slab = NULL;
517 }
518}