diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:30:19 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:45:36 -0400 |
commit | 4829007c7bc689cbc290fc09eccbe90bd52c2a5e (patch) | |
tree | f8f2058b9db8e8df7b4cb2f1f850ca3115e5c58f /net/dccp/options.c | |
parent | ff49e27089ec363b7fc3849504e0435d447ab18a (diff) |
dccp ccid-2: Separate internals of Ack Vectors from option-parsing code
This patch
* separates Ack Vector housekeeping code from option-insertion code;
* shifts option-specific code from ackvec.c into options.c;
* introduces a dedicated routine to take care of the Ack Vector records;
* simplifies the dccp_ackvec_insert_avr() routine: the BUG_ON was redundant,
since the list is automatically arranged in descending order of ack_seqno.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index 9fe0510f4022..392d7db31342 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -428,6 +428,66 @@ static int dccp_insert_option_timestamp_echo(struct dccp_sock *dp, | |||
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | 430 | ||
431 | static int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | ||
432 | { | ||
433 | struct dccp_sock *dp = dccp_sk(sk); | ||
434 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | ||
435 | /* Figure out how many options do we need to represent the ackvec */ | ||
436 | const u8 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_SINGLE_OPT_MAXLEN); | ||
437 | u16 len = av->av_vec_len + 2 * nr_opts; | ||
438 | u8 i, nonce = 0; | ||
439 | const unsigned char *tail, *from; | ||
440 | unsigned char *to; | ||
441 | |||
442 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) | ||
443 | return -1; | ||
444 | |||
445 | DCCP_SKB_CB(skb)->dccpd_opt_len += len; | ||
446 | |||
447 | to = skb_push(skb, len); | ||
448 | len = av->av_vec_len; | ||
449 | from = av->av_buf + av->av_buf_head; | ||
450 | tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN; | ||
451 | |||
452 | for (i = 0; i < nr_opts; ++i) { | ||
453 | int copylen = len; | ||
454 | |||
455 | if (len > DCCP_SINGLE_OPT_MAXLEN) | ||
456 | copylen = DCCP_SINGLE_OPT_MAXLEN; | ||
457 | |||
458 | /* | ||
459 | * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via | ||
460 | * its type; ack_nonce is the sum of all individual buf_nonce's. | ||
461 | */ | ||
462 | nonce ^= av->av_buf_nonce[i]; | ||
463 | |||
464 | *to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i]; | ||
465 | *to++ = copylen + 2; | ||
466 | |||
467 | /* Check if buf_head wraps */ | ||
468 | if (from + copylen > tail) { | ||
469 | const u16 tailsize = tail - from; | ||
470 | |||
471 | memcpy(to, from, tailsize); | ||
472 | to += tailsize; | ||
473 | len -= tailsize; | ||
474 | copylen -= tailsize; | ||
475 | from = av->av_buf; | ||
476 | } | ||
477 | |||
478 | memcpy(to, from, copylen); | ||
479 | from += copylen; | ||
480 | to += copylen; | ||
481 | len -= copylen; | ||
482 | } | ||
483 | /* | ||
484 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. | ||
485 | */ | ||
486 | if (dccp_ackvec_update_records(av, DCCP_SKB_CB(skb)->dccpd_seq, nonce)) | ||
487 | return -ENOBUFS; | ||
488 | return 0; | ||
489 | } | ||
490 | |||
431 | /** | 491 | /** |
432 | * dccp_insert_option_mandatory - Mandatory option (5.8.2) | 492 | * dccp_insert_option_mandatory - Mandatory option (5.8.2) |
433 | * Note that since we are using skb_push, this function needs to be called | 493 | * Note that since we are using skb_push, this function needs to be called |