aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@ghostprotocols.net>2005-08-09 23:14:34 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:49:46 -0400
commit7c657876b63cb1d8a2ec06f8fc6c37bb8412e66c (patch)
tree3cb2732870c9cf8f976cb6fa57e0223f1c648e2a /net/dccp/options.c
parentc4365c9235f80128c3c3d5993074173941b1c1f0 (diff)
[DCCP]: Initial implementation
Development to this point was done on a subversion repository at: http://oops.ghostprotocols.net:81/cgi-bin/viewcvs.cgi/dccp-2.6/ This repository will be kept at this site for the foreseable future, so that interested parties can see the history of this code, attributions, etc. If I ever decide to take this offline I'll provide the full history at some other suitable place. Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r--net/dccp/options.c763
1 files changed, 763 insertions, 0 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c
new file mode 100644
index 000000000000..e1867767946c
--- /dev/null
+++ b/net/dccp/options.c
@@ -0,0 +1,763 @@
1/*
2 * net/dccp/options.c
3 *
4 * An implementation of the DCCP protocol
5 * Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
6 * Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <linux/config.h>
14#include <linux/dccp.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18#include <linux/skbuff.h>
19
20#include "ccid.h"
21#include "dccp.h"
22
23static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
24 struct sock *sk,
25 const u64 ackno,
26 const unsigned char len,
27 const unsigned char *vector);
28
29/* stores the default values for new connection. may be changed with sysctl */
30static const struct dccp_options dccpo_default_values = {
31 .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW,
32 .dccpo_ccid = DCCPF_INITIAL_CCID,
33 .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR,
34 .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT,
35};
36
37void dccp_options_init(struct dccp_options *dccpo)
38{
39 memcpy(dccpo, &dccpo_default_values, sizeof(*dccpo));
40}
41
42static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
43{
44 u32 value = 0;
45
46 if (len > 3)
47 value += *bf++ << 24;
48 if (len > 2)
49 value += *bf++ << 16;
50 if (len > 1)
51 value += *bf++ << 8;
52 if (len > 0)
53 value += *bf;
54
55 return value;
56}
57
58int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
59{
60 struct dccp_sock *dp = dccp_sk(sk);
61#ifdef DCCP_DEBUG
62 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT rx opt: " :
63 "server rx opt: ";
64#endif
65 const struct dccp_hdr *dh = dccp_hdr(skb);
66 const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type;
67 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
68 unsigned char *opt_ptr = options;
69 const unsigned char *opt_end = (unsigned char *)dh + (dh->dccph_doff * 4);
70 struct dccp_options_received *opt_recv = &dp->dccps_options_received;
71 unsigned char opt, len;
72 unsigned char *value;
73
74 memset(opt_recv, 0, sizeof(*opt_recv));
75
76 while (opt_ptr != opt_end) {
77 opt = *opt_ptr++;
78 len = 0;
79 value = NULL;
80
81 /* Check if this isn't a single byte option */
82 if (opt > DCCPO_MAX_RESERVED) {
83 if (opt_ptr == opt_end)
84 goto out_invalid_option;
85
86 len = *opt_ptr++;
87 if (len < 3)
88 goto out_invalid_option;
89 /*
90 * Remove the type and len fields, leaving
91 * just the value size
92 */
93 len -= 2;
94 value = opt_ptr;
95 opt_ptr += len;
96
97 if (opt_ptr > opt_end)
98 goto out_invalid_option;
99 }
100
101 switch (opt) {
102 case DCCPO_PADDING:
103 break;
104 case DCCPO_NDP_COUNT:
105 if (len > 3)
106 goto out_invalid_option;
107
108 opt_recv->dccpor_ndp = dccp_decode_value_var(value, len);
109 dccp_pr_debug("%sNDP count=%d\n", debug_prefix, opt_recv->dccpor_ndp);
110 break;
111 case DCCPO_ACK_VECTOR_0:
112 if (len > DCCP_MAX_ACK_VECTOR_LEN)
113 goto out_invalid_option;
114
115 if (pkt_type == DCCP_PKT_DATA)
116 continue;
117
118 opt_recv->dccpor_ack_vector_len = len;
119 opt_recv->dccpor_ack_vector_idx = value - options;
120
121 dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n",
122 debug_prefix, len, DCCP_SKB_CB(skb)->dccpd_ack_seq);
123 dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq,
124 value, len);
125 dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts, sk,
126 DCCP_SKB_CB(skb)->dccpd_ack_seq,
127 len, value);
128 break;
129 case DCCPO_TIMESTAMP:
130 if (len != 4)
131 goto out_invalid_option;
132
133 opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
134
135 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
136 dp->dccps_timestamp_time = jiffies;
137
138 dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
139 debug_prefix, opt_recv->dccpor_timestamp,
140 DCCP_SKB_CB(skb)->dccpd_ack_seq);
141 break;
142 case DCCPO_TIMESTAMP_ECHO:
143 if (len < 4 || len > 8)
144 goto out_invalid_option;
145
146 opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value);
147
148 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, diff=%u\n",
149 debug_prefix, opt_recv->dccpor_timestamp_echo,
150 len + 2, DCCP_SKB_CB(skb)->dccpd_ack_seq,
151 tcp_time_stamp - opt_recv->dccpor_timestamp_echo);
152
153 opt_recv->dccpor_elapsed_time = dccp_decode_value_var(value + 4, len - 4);
154 dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n", debug_prefix,
155 opt_recv->dccpor_elapsed_time);
156 break;
157 case DCCPO_ELAPSED_TIME:
158 if (len > 4)
159 goto out_invalid_option;
160
161 if (pkt_type == DCCP_PKT_DATA)
162 continue;
163 opt_recv->dccpor_elapsed_time = dccp_decode_value_var(value, len);
164 dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
165 opt_recv->dccpor_elapsed_time);
166 break;
167 /*
168 * From draft-ietf-dccp-spec-11.txt:
169 *
170 * Option numbers 128 through 191 are for options sent from the HC-
171 * Sender to the HC-Receiver; option numbers 192 through 255 are for
172 * options sent from the HC-Receiver to the HC-Sender.
173 */
174 case 128 ... 191: {
175 const u16 idx = value - options;
176
177 if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, opt, len, idx, value) != 0)
178 goto out_invalid_option;
179 }
180 break;
181 case 192 ... 255: {
182 const u16 idx = value - options;
183
184 if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, opt, len, idx, value) != 0)
185 goto out_invalid_option;
186 }
187 break;
188 default:
189 pr_info("DCCP(%p): option %d(len=%d) not implemented, ignoring\n",
190 sk, opt, len);
191 break;
192 }
193 }
194
195 return 0;
196
197out_invalid_option:
198 DCCP_INC_STATS_BH(DCCP_MIB_INVALIDOPT);
199 DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_OPTION_ERROR;
200 pr_info("DCCP(%p): invalid option %d, len=%d\n", sk, opt, len);
201 return -1;
202}
203
204static void dccp_encode_value_var(const u32 value, unsigned char *to,
205 const unsigned int len)
206{
207 if (len > 3)
208 *to++ = (value & 0xFF000000) >> 24;
209 if (len > 2)
210 *to++ = (value & 0xFF0000) >> 16;
211 if (len > 1)
212 *to++ = (value & 0xFF00) >> 8;
213 if (len > 0)
214 *to++ = (value & 0xFF);
215}
216
217static inline int dccp_ndp_len(const int ndp)
218{
219 return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
220}
221
222void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
223 const unsigned char option,
224 const void *value, const unsigned char len)
225{
226 unsigned char *to;
227
228 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) {
229 LIMIT_NETDEBUG(pr_info("DCCP: packet too small to insert %d option!\n", option));
230 return;
231 }
232
233 DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
234
235 to = skb_push(skb, len + 2);
236 *to++ = option;
237 *to++ = len + 2;
238
239 memcpy(to, value, len);
240}
241
242EXPORT_SYMBOL_GPL(dccp_insert_option);
243
244static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
245{
246 struct dccp_sock *dp = dccp_sk(sk);
247 int ndp = dp->dccps_ndp_count;
248
249 if (dccp_non_data_packet(skb))
250 ++dp->dccps_ndp_count;
251 else
252 dp->dccps_ndp_count = 0;
253
254 if (ndp > 0) {
255 unsigned char *ptr;
256 const int ndp_len = dccp_ndp_len(ndp);
257 const int len = ndp_len + 2;
258
259 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
260 return;
261
262 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
263
264 ptr = skb_push(skb, len);
265 *ptr++ = DCCPO_NDP_COUNT;
266 *ptr++ = len;
267 dccp_encode_value_var(ndp, ptr, ndp_len);
268 }
269}
270
271static inline int dccp_elapsed_time_len(const u32 elapsed_time)
272{
273 return elapsed_time == 0 ? 0 :
274 elapsed_time <= 0xFF ? 1 :
275 elapsed_time <= 0xFFFF ? 2 :
276 elapsed_time <= 0xFFFFFF ? 3 : 4;
277}
278
279void dccp_insert_option_elapsed_time(struct sock *sk,
280 struct sk_buff *skb,
281 u32 elapsed_time)
282{
283#ifdef DCCP_DEBUG
284 struct dccp_sock *dp = dccp_sk(sk);
285 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT TX opt: " :
286 "server TX opt: ";
287#endif
288 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
289 const int len = 2 + elapsed_time_len;
290 unsigned char *to;
291
292 /* If elapsed_time == 0... */
293 if (elapsed_time_len == 2)
294 return;
295
296 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
297 LIMIT_NETDEBUG(pr_info("DCCP: packet too small to insert elapsed time!\n"));
298 return;
299 }
300
301 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
302
303 to = skb_push(skb, len);
304 *to++ = DCCPO_ELAPSED_TIME;
305 *to++ = len;
306
307 dccp_encode_value_var(elapsed_time, to, elapsed_time_len);
308
309 dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n",
310 debug_prefix, elapsed_time,
311 len, DCCP_SKB_CB(skb)->dccpd_seq);
312}
313
314EXPORT_SYMBOL(dccp_insert_option_elapsed_time);
315
316static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
317{
318 struct dccp_sock *dp = dccp_sk(sk);
319#ifdef DCCP_DEBUG
320 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT TX opt: " :
321 "server TX opt: ";
322#endif
323 struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
324 int len = ap->dccpap_buf_vector_len + 2;
325 const u32 elapsed_time = jiffies_to_usecs(jiffies - ap->dccpap_time) / 10;
326 unsigned char *to, *from;
327
328 if (elapsed_time != 0)
329 dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
330
331 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
332 LIMIT_NETDEBUG(pr_info("DCCP: packet too small to insert ACK Vector!\n"));
333 return;
334 }
335
336 /*
337 * XXX: now we have just one ack vector sent record, so
338 * we have to wait for it to be cleared.
339 *
340 * Of course this is not acceptable, but this is just for
341 * basic testing now.
342 */
343 if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1)
344 return;
345
346 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
347
348 to = skb_push(skb, len);
349 *to++ = DCCPO_ACK_VECTOR_0;
350 *to++ = len;
351
352 len = ap->dccpap_buf_vector_len;
353 from = ap->dccpap_buf + ap->dccpap_buf_head;
354
355 /* Check if buf_head wraps */
356 if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) {
357 const unsigned int tailsize = ap->dccpap_buf_len - ap->dccpap_buf_head;
358
359 memcpy(to, from, tailsize);
360 to += tailsize;
361 len -= tailsize;
362 from = ap->dccpap_buf;
363 }
364
365 memcpy(to, from, len);
366 /*
367 * From draft-ietf-dccp-spec-11.txt:
368 *
369 * For each acknowledgement it sends, the HC-Receiver will add an
370 * acknowledgement record. ack_seqno will equal the HC-Receiver
371 * sequence number it used for the ack packet; ack_ptr will equal
372 * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will equal
373 * buf_nonce.
374 *
375 * This implemention uses just one ack record for now.
376 */
377 ap->dccpap_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
378 ap->dccpap_ack_ptr = ap->dccpap_buf_head;
379 ap->dccpap_ack_ackno = ap->dccpap_buf_ackno;
380 ap->dccpap_ack_nonce = ap->dccpap_buf_nonce;
381 ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len;
382
383 dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, ack_ackno=%llu\n",
384 debug_prefix, ap->dccpap_ack_vector_len,
385 ap->dccpap_ack_seqno, ap->dccpap_ack_ackno);
386}
387
388static inline void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
389{
390 const u32 now = htonl(tcp_time_stamp);
391 dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
392}
393
394static void dccp_insert_option_timestamp_echo(struct sock *sk, struct sk_buff *skb)
395{
396 struct dccp_sock *dp = dccp_sk(sk);
397#ifdef DCCP_DEBUG
398 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT TX opt: " :
399 "server TX opt: ";
400#endif
401 u32 tstamp_echo;
402 const u32 elapsed_time = jiffies_to_usecs(jiffies - dp->dccps_timestamp_time) / 10;
403 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
404 const int len = 6 + elapsed_time_len;
405 unsigned char *to;
406
407 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
408 LIMIT_NETDEBUG(pr_info("DCCP: packet too small to insert timestamp echo!\n"));
409 return;
410 }
411
412 DCCP_SKB_CB(skb)->dccpd_opt_len += len;
413
414 to = skb_push(skb, len);
415 *to++ = DCCPO_TIMESTAMP_ECHO;
416 *to++ = len;
417
418 tstamp_echo = htonl(dp->dccps_timestamp_echo);
419 memcpy(to, &tstamp_echo, 4);
420 to += 4;
421 dccp_encode_value_var(elapsed_time, to, elapsed_time_len);
422
423 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
424 debug_prefix, dp->dccps_timestamp_echo,
425 len, DCCP_SKB_CB(skb)->dccpd_seq);
426
427 dp->dccps_timestamp_echo = 0;
428 dp->dccps_timestamp_time = 0;
429}
430
431void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
432{
433 struct dccp_sock *dp = dccp_sk(sk);
434
435 DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
436
437 if (dp->dccps_options.dccpo_send_ndp_count)
438 dccp_insert_option_ndp(sk, skb);
439
440 if (!dccp_packet_without_ack(skb)) {
441 if (dp->dccps_options.dccpo_send_ack_vector &&
442 dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1)
443 dccp_insert_option_ack_vector(sk, skb);
444
445 dccp_insert_option_timestamp(sk, skb);
446 if (dp->dccps_timestamp_echo != 0)
447 dccp_insert_option_timestamp_echo(sk, skb);
448 }
449
450 ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
451 ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
452
453 /* XXX: insert other options when appropriate */
454
455 if (DCCP_SKB_CB(skb)->dccpd_opt_len != 0) {
456 /* The length of all options has to be a multiple of 4 */
457 int padding = DCCP_SKB_CB(skb)->dccpd_opt_len % 4;
458
459 if (padding != 0) {
460 padding = 4 - padding;
461 memset(skb_push(skb, padding), 0, padding);
462 DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
463 }
464 }
465}
466
467struct dccp_ackpkts *dccp_ackpkts_alloc(unsigned int len, int priority)
468{
469 struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority);
470
471 if (ap != NULL) {
472#ifdef DCCP_DEBUG
473 memset(ap->dccpap_buf, 0xFF, len);
474#endif
475 ap->dccpap_buf_len = len;
476 ap->dccpap_buf_head = ap->dccpap_buf_tail = ap->dccpap_buf_len - 1;
477 ap->dccpap_buf_ackno = ap->dccpap_ack_ackno = ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
478 ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0;
479 ap->dccpap_ack_ptr = 0;
480 ap->dccpap_time = 0;
481 ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0;
482 }
483
484 return ap;
485}
486
487void dccp_ackpkts_free(struct dccp_ackpkts *ap)
488{
489 if (ap != NULL) {
490#ifdef DCCP_DEBUG
491 memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len);
492#endif
493 kfree(ap);
494 }
495}
496
497static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap,
498 const unsigned int index)
499{
500 return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK;
501}
502
503static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap,
504 const unsigned int index)
505{
506 return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK;
507}
508
509/*
510 * If several packets are missing, the HC-Receiver may prefer to enter multiple
511 * bytes with run length 0, rather than a single byte with a larger run length;
512 * this simplifies table updates if one of the missing packets arrives.
513 */
514static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
515 const unsigned int packets,
516 const unsigned char state)
517{
518 unsigned int gap;
519 signed long new_head;
520
521 if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len)
522 return -ENOBUFS;
523
524 gap = packets - 1;
525 new_head = ap->dccpap_buf_head - packets;
526
527 if (new_head < 0) {
528 if (gap > 0) {
529 memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED,
530 gap + new_head + 1);
531 gap = -new_head;
532 }
533 new_head += ap->dccpap_buf_len;
534 }
535
536 ap->dccpap_buf_head = new_head;
537
538 if (gap > 0)
539 memset(ap->dccpap_buf + ap->dccpap_buf_head + 1,
540 DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap);
541
542 ap->dccpap_buf[ap->dccpap_buf_head] = state;
543 ap->dccpap_buf_vector_len += packets;
544 return 0;
545}
546
547/*
548 * Implements the draft-ietf-dccp-spec-11.txt Appendix A
549 */
550int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
551{
552 /*
553 * Check at the right places if the buffer is full, if it is, tell the
554 * caller to start dropping packets till the HC-Sender acks our ACK
555 * vectors, when we will free up space in dccpap_buf.
556 *
557 * We may well decide to do buffer compression, etc, but for now lets
558 * just drop.
559 *
560 * From Appendix A:
561 *
562 * Of course, the circular buffer may overflow, either when the HC-
563 * Sender is sending data at a very high rate, when the HC-Receiver's
564 * acknowledgements are not reaching the HC-Sender, or when the HC-
565 * Sender is forgetting to acknowledge those acks (so the HC-Receiver
566 * is unable to clean up old state). In this case, the HC-Receiver
567 * should either compress the buffer (by increasing run lengths when
568 * possible), transfer its state to a larger buffer, or, as a last
569 * resort, drop all received packets, without processing them
570 * whatsoever, until its buffer shrinks again.
571 */
572
573 /* See if this is the first ackno being inserted */
574 if (ap->dccpap_buf_vector_len == 0) {
575 ap->dccpap_buf[ap->dccpap_buf_head] = state;
576 ap->dccpap_buf_vector_len = 1;
577 } else if (after48(ackno, ap->dccpap_buf_ackno)) {
578 const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno, ackno);
579
580 /*
581 * Look if the state of this packet is the same as the previous ackno
582 * and if so if we can bump the head len.
583 */
584 if (delta == 1 &&
585 dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state &&
586 dccp_ackpkts_len(ap, ap->dccpap_buf_head) < DCCP_ACKPKTS_LEN_MASK)
587 ap->dccpap_buf[ap->dccpap_buf_head]++;
588 else if (dccp_ackpkts_set_buf_head_state(ap, delta, state))
589 return -ENOBUFS;
590 } else {
591 /*
592 * A.1.2. Old Packets
593 *
594 * When a packet with Sequence Number S arrives, and S <= buf_ackno,
595 * the HC-Receiver will scan the table for the byte corresponding to S.
596 * (Indexing structures could reduce the complexity of this scan.)
597 */
598 u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno);
599 unsigned int index = ap->dccpap_buf_head;
600
601 while (1) {
602 const u8 len = dccp_ackpkts_len(ap, index);
603 const u8 state = dccp_ackpkts_state(ap, index);
604 /*
605 * valid packets not yet in dccpap_buf have a reserved entry, with
606 * a len equal to 0
607 */
608 if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED &&
609 len == 0 && delta == 0) { /* Found our reserved seat! */
610 dccp_pr_debug("Found %llu reserved seat!\n", ackno);
611 ap->dccpap_buf[index] = state;
612 goto out;
613 }
614 /* len == 0 means one packet */
615 if (delta < len + 1)
616 goto out_duplicate;
617
618 delta -= len + 1;
619 if (++index == ap->dccpap_buf_len)
620 index = 0;
621 }
622 }
623
624 ap->dccpap_buf_ackno = ackno;
625 ap->dccpap_time = jiffies;
626out:
627 dccp_pr_debug("");
628 dccp_ackpkts_print(ap);
629 return 0;
630
631out_duplicate:
632 /* Duplicate packet */
633 dccp_pr_debug("Received a dup or already considered lost packet: %llu\n", ackno);
634 return -EILSEQ;
635}
636
637#ifdef DCCP_DEBUG
638void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len)
639{
640 if (!dccp_debug)
641 return;
642
643 printk("ACK vector len=%d, ackno=%llu |", len, ackno);
644
645 while (len--) {
646 const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6;
647 const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
648
649 printk("%d,%d|", state, rl);
650 ++vector;
651 }
652
653 printk("\n");
654}
655
656void dccp_ackpkts_print(const struct dccp_ackpkts *ap)
657{
658 dccp_ackvector_print(ap->dccpap_buf_ackno,
659 ap->dccpap_buf + ap->dccpap_buf_head,
660 ap->dccpap_buf_vector_len);
661}
662#endif
663
664static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap)
665{
666 /*
667 * As we're keeping track of the ack vector size
668 * (dccpap_buf_vector_len) and the sent ack vector size
669 * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but
670 * keep this code here as in the future we'll implement a vector of ack
671 * records, as suggested in draft-ietf-dccp-spec-11.txt Appendix A. -acme
672 */
673#if 0
674 ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1;
675 if (ap->dccpap_buf_tail >= ap->dccpap_buf_len)
676 ap->dccpap_buf_tail -= ap->dccpap_buf_len;
677#endif
678 ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len;
679}
680
681void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk,
682 u64 ackno)
683{
684 /* Check if we actually sent an ACK vector */
685 if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
686 return;
687
688 if (ackno == ap->dccpap_ack_seqno) {
689#ifdef DCCP_DEBUG
690 struct dccp_sock *dp = dccp_sk(sk);
691 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT rx ack: " :
692 "server rx ack: ";
693#endif
694 dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, ack_ackno=%llu, ACKED!\n",
695 debug_prefix, 1,
696 ap->dccpap_ack_seqno, ap->dccpap_ack_ackno);
697 dccp_ackpkts_trow_away_ack_record(ap);
698 ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
699 }
700}
701
702static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap,
703 struct sock *sk, u64 ackno,
704 const unsigned char len,
705 const unsigned char *vector)
706{
707 unsigned char i;
708
709 /* Check if we actually sent an ACK vector */
710 if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)
711 return;
712 /*
713 * We're in the receiver half connection, so if the received an ACK vector
714 * ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're not interested.
715 *
716 * Extra explanation with example:
717 *
718 * if we received an ACK vector with ackno 50, it can only be acking
719 * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent).
720 */
721 // dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno);
722 if (before48(ackno, ap->dccpap_ack_seqno)) {
723 // dccp_pr_debug_cat("yes\n");
724 return;
725 }
726 // dccp_pr_debug_cat("no\n");
727
728 i = len;
729 while (i--) {
730 const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK);
731 u64 ackno_end_rl;
732
733 dccp_set_seqno(&ackno_end_rl, ackno - rl);
734
735 // dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, ap->dccpap_ack_seqno, ackno);
736 if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) {
737 const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6;
738 // dccp_pr_debug_cat("yes\n");
739
740 if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) {
741#ifdef DCCP_DEBUG
742 struct dccp_sock *dp = dccp_sk(sk);
743 const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT rx ack: " :
744 "server rx ack: ";
745#endif
746 dccp_pr_debug("%sACK vector 0, len=%d, ack_seqno=%llu, ack_ackno=%llu, ACKED!\n",
747 debug_prefix, len,
748 ap->dccpap_ack_seqno, ap->dccpap_ack_ackno);
749 dccp_ackpkts_trow_away_ack_record(ap);
750 }
751 /*
752 * If dccpap_ack_seqno was not received, no problem we'll
753 * send another ACK vector.
754 */
755 ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
756 break;
757 }
758 // dccp_pr_debug_cat("no\n");
759
760 dccp_set_seqno(&ackno, ackno_end_rl - 1);
761 ++vector;
762 }
763}