diff options
Diffstat (limited to 'net/dccp/ackvec.c')
-rw-r--r-- | net/dccp/ackvec.c | 116 |
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, | |||
67 | int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | 67 | int 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 | ||
176 | static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, | 189 | static 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 | ||
182 | static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, | 195 | static 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 |
323 | void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len) | 336 | void 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 | ||
342 | void dccp_ackvec_print(const struct dccp_ackvec *av) | 352 | void 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 | ||
399 | static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | 405 | static 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; |
436 | found: | 442 | found: |
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 | ||
468 | int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | 468 | int 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 | ||
481 | static char dccp_ackvec_slab_msg[] __initdata = | ||
482 | KERN_CRIT "DCCP: Unable to create ack vectors slab caches\n"; | ||
483 | |||
484 | int __init dccp_ackvec_init(void) | 480 | int __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; |
504 | out_err: | 500 | out_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 | ||