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.c116
1 files changed, 56 insertions, 60 deletions
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index f8208874ac7d..bdf1bb7a82c0 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -67,15 +67,16 @@ static void dccp_ackvec_insert_avr(struct dccp_ackvec *av,
67int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) 67int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
68{ 68{
69 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
74 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; 70 struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec;
75 int len = av->dccpav_vec_len + 2; 71 /* Figure out how many options do we need to represent the ackvec */
72 const u16 nr_opts = (av->dccpav_vec_len +
73 DCCP_MAX_ACKVEC_OPT_LEN - 1) /
74 DCCP_MAX_ACKVEC_OPT_LEN;
75 u16 len = av->dccpav_vec_len + 2 * nr_opts, i;
76 struct timeval now; 76 struct timeval now;
77 u32 elapsed_time; 77 u32 elapsed_time;
78 unsigned char *to, *from; 78 const unsigned char *tail, *from;
79 unsigned char *to;
79 struct dccp_ackvec_record *avr; 80 struct dccp_ackvec_record *avr;
80 81
81 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) 82 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
@@ -94,24 +95,37 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
94 95
95 DCCP_SKB_CB(skb)->dccpd_opt_len += len; 96 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
96 97
97 to = skb_push(skb, len); 98 to = skb_push(skb, len);
98 *to++ = DCCPO_ACK_VECTOR_0;
99 *to++ = len;
100
101 len = av->dccpav_vec_len; 99 len = av->dccpav_vec_len;
102 from = av->dccpav_buf + av->dccpav_buf_head; 100 from = av->dccpav_buf + av->dccpav_buf_head;
101 tail = av->dccpav_buf + DCCP_MAX_ACKVEC_LEN;
102
103 for (i = 0; i < nr_opts; ++i) {
104 int copylen = len;
103 105
104 /* Check if buf_head wraps */ 106 if (len > DCCP_MAX_ACKVEC_OPT_LEN)
105 if ((int)av->dccpav_buf_head + len > DCCP_MAX_ACKVEC_LEN) { 107 copylen = DCCP_MAX_ACKVEC_OPT_LEN;
106 const u32 tailsize = DCCP_MAX_ACKVEC_LEN - av->dccpav_buf_head; 108
109 *to++ = DCCPO_ACK_VECTOR_0;
110 *to++ = copylen + 2;
111
112 /* Check if buf_head wraps */
113 if (from + copylen > tail) {
114 const u16 tailsize = tail - from;
115
116 memcpy(to, from, tailsize);
117 to += tailsize;
118 len -= tailsize;
119 copylen -= tailsize;
120 from = av->dccpav_buf;
121 }
107 122
108 memcpy(to, from, tailsize); 123 memcpy(to, from, copylen);
109 to += tailsize; 124 from += copylen;
110 len -= tailsize; 125 to += copylen;
111 from = av->dccpav_buf; 126 len -= copylen;
112 } 127 }
113 128
114 memcpy(to, from, len);
115 /* 129 /*
116 * From RFC 4340, A.2: 130 * From RFC 4340, A.2:
117 * 131 *
@@ -129,9 +143,9 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
129 143
130 dccp_ackvec_insert_avr(av, avr); 144 dccp_ackvec_insert_avr(av, avr);
131 145
132 dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " 146 dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, "
133 "ack_ackno=%llu\n", 147 "ack_ackno=%llu\n",
134 debug_prefix, avr->dccpavr_sent_len, 148 dccp_role(sk), avr->dccpavr_sent_len,
135 (unsigned long long)avr->dccpavr_ack_seqno, 149 (unsigned long long)avr->dccpavr_ack_seqno,
136 (unsigned long long)avr->dccpavr_ack_ackno); 150 (unsigned long long)avr->dccpavr_ack_ackno);
137 return 0; 151 return 0;
@@ -145,7 +159,6 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
145 av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1; 159 av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1;
146 av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1; 160 av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1;
147 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; 161 av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0;
148 av->dccpav_ack_ptr = 0;
149 av->dccpav_time.tv_sec = 0; 162 av->dccpav_time.tv_sec = 0;
150 av->dccpav_time.tv_usec = 0; 163 av->dccpav_time.tv_usec = 0;
151 av->dccpav_vec_len = 0; 164 av->dccpav_vec_len = 0;
@@ -174,13 +187,13 @@ void dccp_ackvec_free(struct dccp_ackvec *av)
174} 187}
175 188
176static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, 189static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
177 const u8 index) 190 const u32 index)
178{ 191{
179 return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; 192 return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK;
180} 193}
181 194
182static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, 195static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
183 const u8 index) 196 const u32 index)
184{ 197{
185 return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; 198 return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
186} 199}
@@ -280,7 +293,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
280 * could reduce the complexity of this scan.) 293 * could reduce the complexity of this scan.)
281 */ 294 */
282 u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); 295 u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
283 u8 index = av->dccpav_buf_head; 296 u32 index = av->dccpav_buf_head;
284 297
285 while (1) { 298 while (1) {
286 const u8 len = dccp_ackvec_len(av, index); 299 const u8 len = dccp_ackvec_len(av, index);
@@ -322,21 +335,18 @@ out_duplicate:
322#ifdef CONFIG_IP_DCCP_DEBUG 335#ifdef CONFIG_IP_DCCP_DEBUG
323void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len) 336void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
324{ 337{
325 if (!dccp_debug) 338 dccp_pr_debug_cat("ACK vector len=%d, ackno=%llu |", len,
326 return; 339 (unsigned long long)ackno);
327
328 printk("ACK vector len=%d, ackno=%llu |", len,
329 (unsigned long long)ackno);
330 340
331 while (len--) { 341 while (len--) {
332 const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6; 342 const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6;
333 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; 343 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
334 344
335 printk("%d,%d|", state, rl); 345 dccp_pr_debug_cat("%d,%d|", state, rl);
336 ++vector; 346 ++vector;
337 } 347 }
338 348
339 printk("\n"); 349 dccp_pr_debug_cat("\n");
340} 350}
341 351
342void dccp_ackvec_print(const struct dccp_ackvec *av) 352void dccp_ackvec_print(const struct dccp_ackvec *av)
@@ -380,24 +390,20 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
380 */ 390 */
381 list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) { 391 list_for_each_entry_reverse(avr, &av->dccpav_records, dccpavr_node) {
382 if (ackno == avr->dccpavr_ack_seqno) { 392 if (ackno == avr->dccpavr_ack_seqno) {
383#ifdef CONFIG_IP_DCCP_DEBUG 393 dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, "
384 struct dccp_sock *dp = dccp_sk(sk);
385 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
386 "CLIENT rx ack: " : "server rx ack: ";
387#endif
388 dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, "
389 "ack_ackno=%llu, ACKED!\n", 394 "ack_ackno=%llu, ACKED!\n",
390 debug_prefix, 1, 395 dccp_role(sk), 1,
391 (unsigned long long)avr->dccpavr_ack_seqno, 396 (unsigned long long)avr->dccpavr_ack_seqno,
392 (unsigned long long)avr->dccpavr_ack_ackno); 397 (unsigned long long)avr->dccpavr_ack_ackno);
393 dccp_ackvec_throw_record(av, avr); 398 dccp_ackvec_throw_record(av, avr);
394 break; 399 break;
395 } 400 } else if (avr->dccpavr_ack_seqno > ackno)
401 break; /* old news */
396 } 402 }
397} 403}
398 404
399static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, 405static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
400 struct sock *sk, u64 ackno, 406 struct sock *sk, u64 *ackno,
401 const unsigned char len, 407 const unsigned char len,
402 const unsigned char *vector) 408 const unsigned char *vector)
403{ 409{
@@ -420,7 +426,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
420 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; 426 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
421 u64 ackno_end_rl; 427 u64 ackno_end_rl;
422 428
423 dccp_set_seqno(&ackno_end_rl, ackno - rl); 429 dccp_set_seqno(&ackno_end_rl, *ackno - rl);
424 430
425 /* 431 /*
426 * If our AVR sequence number is greater than the ack, go 432 * If our AVR sequence number is greater than the ack, go
@@ -428,25 +434,19 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
428 */ 434 */
429 list_for_each_entry_from(avr, &av->dccpav_records, 435 list_for_each_entry_from(avr, &av->dccpav_records,
430 dccpavr_node) { 436 dccpavr_node) {
431 if (!after48(avr->dccpavr_ack_seqno, ackno)) 437 if (!after48(avr->dccpavr_ack_seqno, *ackno))
432 goto found; 438 goto found;
433 } 439 }
434 /* End of the dccpav_records list, not found, exit */ 440 /* End of the dccpav_records list, not found, exit */
435 break; 441 break;
436found: 442found:
437 if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) { 443 if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, *ackno)) {
438 const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; 444 const u8 state = *vector & DCCP_ACKVEC_STATE_MASK;
439 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { 445 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) {
440#ifdef CONFIG_IP_DCCP_DEBUG 446 dccp_pr_debug("%s ACK vector 0, len=%d, "
441 struct dccp_sock *dp = dccp_sk(sk);
442 const char *debug_prefix =
443 dp->dccps_role == DCCP_ROLE_CLIENT ?
444 "CLIENT rx ack: " : "server rx ack: ";
445#endif
446 dccp_pr_debug("%sACK vector 0, len=%d, "
447 "ack_seqno=%llu, ack_ackno=%llu, " 447 "ack_seqno=%llu, ack_ackno=%llu, "
448 "ACKED!\n", 448 "ACKED!\n",
449 debug_prefix, len, 449 dccp_role(sk), len,
450 (unsigned long long) 450 (unsigned long long)
451 avr->dccpavr_ack_seqno, 451 avr->dccpavr_ack_seqno,
452 (unsigned long long) 452 (unsigned long long)
@@ -460,27 +460,23 @@ found:
460 */ 460 */
461 } 461 }
462 462
463 dccp_set_seqno(&ackno, ackno_end_rl - 1); 463 dccp_set_seqno(ackno, ackno_end_rl - 1);
464 ++vector; 464 ++vector;
465 } 465 }
466} 466}
467 467
468int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, 468int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb,
469 const u8 opt, const u8 *value, const u8 len) 469 u64 *ackno, const u8 opt, const u8 *value, const u8 len)
470{ 470{
471 if (len > DCCP_MAX_ACKVEC_LEN) 471 if (len > DCCP_MAX_ACKVEC_OPT_LEN)
472 return -1; 472 return -1;
473 473
474 /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ 474 /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */
475 dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, 475 dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk,
476 DCCP_SKB_CB(skb)->dccpd_ack_seq, 476 ackno, len, value);
477 len, value);
478 return 0; 477 return 0;
479} 478}
480 479
481static char dccp_ackvec_slab_msg[] __initdata =
482 KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n";
483
484int __init dccp_ackvec_init(void) 480int __init dccp_ackvec_init(void)
485{ 481{
486 dccp_ackvec_slab = kmem_cache_create("dccp_ackvec", 482 dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
@@ -502,7 +498,7 @@ out_destroy_slab:
502 kmem_cache_destroy(dccp_ackvec_slab); 498 kmem_cache_destroy(dccp_ackvec_slab);
503 dccp_ackvec_slab = NULL; 499 dccp_ackvec_slab = NULL;
504out_err: 500out_err:
505 printk(dccp_ackvec_slab_msg); 501 DCCP_CRIT("Unable to create Ack Vector slab cache");
506 return -ENOBUFS; 502 return -ENOBUFS;
507} 503}
508 504