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 | |
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')
-rw-r--r-- | net/dccp/ackvec.c | 100 | ||||
-rw-r--r-- | net/dccp/ackvec.h | 5 | ||||
-rw-r--r-- | net/dccp/options.c | 60 |
3 files changed, 80 insertions, 85 deletions
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 85ad70cfba5b..de84dd34c93f 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c | |||
@@ -52,99 +52,35 @@ void dccp_ackvec_free(struct dccp_ackvec *av) | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | static void dccp_ackvec_insert_avr(struct dccp_ackvec *av, | 55 | /** |
56 | struct dccp_ackvec_record *avr) | 56 | * dccp_ackvec_update_records - Record information about sent Ack Vectors |
57 | { | 57 | * @av: Ack Vector records to update |
58 | /* | 58 | * @seqno: Sequence number of the packet carrying the Ack Vector just sent |
59 | * AVRs are sorted by seqno. Since we are sending them in order, we | 59 | * @nonce_sum: The sum of all buffer nonces contained in the Ack Vector |
60 | * just add the AVR at the head of the list. | 60 | */ |
61 | * -sorbo. | 61 | int dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seqno, u8 nonce_sum) |
62 | */ | ||
63 | if (!list_empty(&av->av_records)) { | ||
64 | const struct dccp_ackvec_record *head = | ||
65 | list_entry(av->av_records.next, | ||
66 | struct dccp_ackvec_record, | ||
67 | avr_node); | ||
68 | BUG_ON(before48(avr->avr_ack_seqno, head->avr_ack_seqno)); | ||
69 | } | ||
70 | |||
71 | list_add(&avr->avr_node, &av->av_records); | ||
72 | } | ||
73 | |||
74 | int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | ||
75 | { | 62 | { |
76 | struct dccp_sock *dp = dccp_sk(sk); | ||
77 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | ||
78 | /* Figure out how many options do we need to represent the ackvec */ | ||
79 | const u8 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_SINGLE_OPT_MAXLEN); | ||
80 | u16 len = av->av_vec_len + 2 * nr_opts; | ||
81 | u8 i, nonce = 0; | ||
82 | const unsigned char *tail, *from; | ||
83 | unsigned char *to; | ||
84 | struct dccp_ackvec_record *avr; | 63 | struct dccp_ackvec_record *avr; |
85 | 64 | ||
86 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) | ||
87 | return -1; | ||
88 | |||
89 | avr = kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC); | 65 | avr = kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC); |
90 | if (avr == NULL) | 66 | if (avr == NULL) |
91 | return -1; | 67 | return -ENOBUFS; |
92 | |||
93 | DCCP_SKB_CB(skb)->dccpd_opt_len += len; | ||
94 | |||
95 | to = skb_push(skb, len); | ||
96 | len = av->av_vec_len; | ||
97 | from = av->av_buf + av->av_buf_head; | ||
98 | tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN; | ||
99 | |||
100 | for (i = 0; i < nr_opts; ++i) { | ||
101 | int copylen = len; | ||
102 | |||
103 | if (len > DCCP_SINGLE_OPT_MAXLEN) | ||
104 | copylen = DCCP_SINGLE_OPT_MAXLEN; | ||
105 | |||
106 | /* | ||
107 | * RFC 4340, 12.2: Encode the Nonce Echo for this Ack Vector via | ||
108 | * its type; ack_nonce is the sum of all individual buf_nonce's. | ||
109 | */ | ||
110 | nonce ^= av->av_buf_nonce[i]; | ||
111 | |||
112 | *to++ = DCCPO_ACK_VECTOR_0 + av->av_buf_nonce[i]; | ||
113 | *to++ = copylen + 2; | ||
114 | |||
115 | /* Check if buf_head wraps */ | ||
116 | if (from + copylen > tail) { | ||
117 | const u16 tailsize = tail - from; | ||
118 | |||
119 | memcpy(to, from, tailsize); | ||
120 | to += tailsize; | ||
121 | len -= tailsize; | ||
122 | copylen -= tailsize; | ||
123 | from = av->av_buf; | ||
124 | } | ||
125 | |||
126 | memcpy(to, from, copylen); | ||
127 | from += copylen; | ||
128 | to += copylen; | ||
129 | len -= copylen; | ||
130 | } | ||
131 | 68 | ||
132 | /* | 69 | avr->avr_ack_seqno = seqno; |
133 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. | ||
134 | */ | ||
135 | avr->avr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; | ||
136 | avr->avr_ack_ptr = av->av_buf_head; | 70 | avr->avr_ack_ptr = av->av_buf_head; |
137 | avr->avr_ack_ackno = av->av_buf_ackno; | 71 | avr->avr_ack_ackno = av->av_buf_ackno; |
138 | avr->avr_ack_nonce = nonce; | 72 | avr->avr_ack_nonce = nonce_sum; |
139 | avr->avr_ack_runlen = dccp_ackvec_runlen(av->av_buf + av->av_buf_head); | 73 | avr->avr_ack_runlen = dccp_ackvec_runlen(av->av_buf + av->av_buf_head); |
74 | /* | ||
75 | * Since GSS is incremented for each packet, the list is automatically | ||
76 | * arranged in descending order of @ack_seqno. | ||
77 | */ | ||
78 | list_add(&avr->avr_node, &av->av_records); | ||
140 | 79 | ||
141 | dccp_ackvec_insert_avr(av, avr); | 80 | dccp_pr_debug("Added Vector, ack_seqno=%llu, ack_ackno=%llu (rl=%u)\n", |
142 | |||
143 | dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, " | ||
144 | "ack_ackno=%llu\n", | ||
145 | dccp_role(sk), avr->avr_ack_runlen, | ||
146 | (unsigned long long)avr->avr_ack_seqno, | 81 | (unsigned long long)avr->avr_ack_seqno, |
147 | (unsigned long long)avr->avr_ack_ackno); | 82 | (unsigned long long)avr->avr_ack_ackno, |
83 | avr->avr_ack_runlen); | ||
148 | return 0; | 84 | return 0; |
149 | } | 85 | } |
150 | 86 | ||
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index df18f9030dbb..b34e5ed4c342 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h | |||
@@ -112,7 +112,7 @@ extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | |||
112 | u64 *ackno, const u8 opt, | 112 | u64 *ackno, const u8 opt, |
113 | const u8 *value, const u8 len); | 113 | const u8 *value, const u8 len); |
114 | 114 | ||
115 | extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); | 115 | extern int dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seq, u8 sum); |
116 | 116 | ||
117 | static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) | 117 | static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) |
118 | { | 118 | { |
@@ -155,8 +155,7 @@ static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | |||
155 | return -1; | 155 | return -1; |
156 | } | 156 | } |
157 | 157 | ||
158 | static inline int dccp_insert_option_ackvec(const struct sock *sk, | 158 | static inline int dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seq, u8 nonce) |
159 | const struct sk_buff *skb) | ||
160 | { | 159 | { |
161 | return -1; | 160 | return -1; |
162 | } | 161 | } |
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 |