diff options
author | Andrea Bittau <a.bittau@cs.ucl.ac.uk> | 2006-11-24 10:02:42 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:30:32 -0500 |
commit | bdf13d208dee4ada6d2b422536a12b45d5831aa3 (patch) | |
tree | ce8c076cce9f8c1bb70d5d6c0f05da2767df3a3f | |
parent | 0bd4ff1b1528a39b07aab6c744ac37e053740ad0 (diff) |
[DCCP] ackvec: infrastructure for sending more than one ackvec per packet
Commiter note:
This was split from Andrea's original patch, in the process I changed the type
of the ackvec index fields to u16 instead of to int and haven't folded
dccp_ackvec_parse with dccp_ackvec_check_rcv_ackno.
Next patch will actually do the insertion of more than one ackvec per packet,
using, initially, up to a max of 2 ackvecs as per Andrea's original patch, then
I'll work on support for larger ackvecs, be it using a sysctl or using
setsockopt.
Signed-off-by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
-rw-r--r-- | net/dccp/ackvec.c | 23 | ||||
-rw-r--r-- | net/dccp/ackvec.h | 18 | ||||
-rw-r--r-- | net/dccp/options.c | 3 |
3 files changed, 24 insertions, 20 deletions
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 215355d993de..41d34d1babc1 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c | |||
@@ -169,13 +169,13 @@ void dccp_ackvec_free(struct dccp_ackvec *av) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, | 171 | static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, |
172 | const u8 index) | 172 | const u32 index) |
173 | { | 173 | { |
174 | return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; | 174 | return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; |
175 | } | 175 | } |
176 | 176 | ||
177 | static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, | 177 | static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, |
178 | const u8 index) | 178 | const u32 index) |
179 | { | 179 | { |
180 | return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; | 180 | return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; |
181 | } | 181 | } |
@@ -275,7 +275,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | |||
275 | * could reduce the complexity of this scan.) | 275 | * could reduce the complexity of this scan.) |
276 | */ | 276 | */ |
277 | u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); | 277 | u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); |
278 | u8 index = av->dccpav_buf_head; | 278 | u32 index = av->dccpav_buf_head; |
279 | 279 | ||
280 | while (1) { | 280 | while (1) { |
281 | const u8 len = dccp_ackvec_len(av, index); | 281 | const u8 len = dccp_ackvec_len(av, index); |
@@ -385,7 +385,7 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, | |||
385 | } | 385 | } |
386 | 386 | ||
387 | static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | 387 | static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, |
388 | struct sock *sk, u64 ackno, | 388 | struct sock *sk, u64 *ackno, |
389 | const unsigned char len, | 389 | const unsigned char len, |
390 | const unsigned char *vector) | 390 | const unsigned char *vector) |
391 | { | 391 | { |
@@ -408,7 +408,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | |||
408 | const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; | 408 | const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; |
409 | u64 ackno_end_rl; | 409 | u64 ackno_end_rl; |
410 | 410 | ||
411 | dccp_set_seqno(&ackno_end_rl, ackno - rl); | 411 | dccp_set_seqno(&ackno_end_rl, *ackno - rl); |
412 | 412 | ||
413 | /* | 413 | /* |
414 | * If our AVR sequence number is greater than the ack, go | 414 | * If our AVR sequence number is greater than the ack, go |
@@ -416,13 +416,13 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | |||
416 | */ | 416 | */ |
417 | list_for_each_entry_from(avr, &av->dccpav_records, | 417 | list_for_each_entry_from(avr, &av->dccpav_records, |
418 | dccpavr_node) { | 418 | dccpavr_node) { |
419 | if (!after48(avr->dccpavr_ack_seqno, ackno)) | 419 | if (!after48(avr->dccpavr_ack_seqno, *ackno)) |
420 | goto found; | 420 | goto found; |
421 | } | 421 | } |
422 | /* End of the dccpav_records list, not found, exit */ | 422 | /* End of the dccpav_records list, not found, exit */ |
423 | break; | 423 | break; |
424 | found: | 424 | found: |
425 | if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) { | 425 | if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, *ackno)) { |
426 | const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; | 426 | const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; |
427 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { | 427 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { |
428 | dccp_pr_debug("%s ACK vector 0, len=%d, " | 428 | dccp_pr_debug("%s ACK vector 0, len=%d, " |
@@ -442,21 +442,20 @@ found: | |||
442 | */ | 442 | */ |
443 | } | 443 | } |
444 | 444 | ||
445 | dccp_set_seqno(&ackno, ackno_end_rl - 1); | 445 | dccp_set_seqno(ackno, ackno_end_rl - 1); |
446 | ++vector; | 446 | ++vector; |
447 | } | 447 | } |
448 | } | 448 | } |
449 | 449 | ||
450 | int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | 450 | int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, |
451 | const u8 opt, const u8 *value, const u8 len) | 451 | u64 *ackno, const u8 opt, const u8 *value, const u8 len) |
452 | { | 452 | { |
453 | if (len > DCCP_MAX_ACKVEC_LEN) | 453 | if (len > DCCP_MAX_ACKVEC_OPT_LEN) |
454 | return -1; | 454 | return -1; |
455 | 455 | ||
456 | /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ | 456 | /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ |
457 | dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, | 457 | dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, |
458 | DCCP_SKB_CB(skb)->dccpd_ack_seq, | 458 | ackno, len, value); |
459 | len, value); | ||
460 | return 0; | 459 | return 0; |
461 | } | 460 | } |
462 | 461 | ||
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index d6a58db5fb13..96504a3b16e4 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h | |||
@@ -17,7 +17,9 @@ | |||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | 18 | ||
19 | /* Read about the ECN nonce to see why it is 253 */ | 19 | /* Read about the ECN nonce to see why it is 253 */ |
20 | #define DCCP_MAX_ACKVEC_LEN 253 | 20 | #define DCCP_MAX_ACKVEC_OPT_LEN 253 |
21 | /* We can spread an ack vector across multiple options */ | ||
22 | #define DCCP_MAX_ACKVEC_LEN (DCCP_MAX_ACKVEC_OPT_LEN * 2) | ||
21 | 23 | ||
22 | #define DCCP_ACKVEC_STATE_RECEIVED 0 | 24 | #define DCCP_ACKVEC_STATE_RECEIVED 0 |
23 | #define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) | 25 | #define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) |
@@ -51,8 +53,8 @@ struct dccp_ackvec { | |||
51 | u64 dccpav_buf_ackno; | 53 | u64 dccpav_buf_ackno; |
52 | struct list_head dccpav_records; | 54 | struct list_head dccpav_records; |
53 | struct timeval dccpav_time; | 55 | struct timeval dccpav_time; |
54 | u8 dccpav_buf_head; | 56 | u16 dccpav_buf_head; |
55 | u8 dccpav_vec_len; | 57 | u16 dccpav_vec_len; |
56 | u8 dccpav_buf_nonce; | 58 | u8 dccpav_buf_nonce; |
57 | u8 dccpav_ack_nonce; | 59 | u8 dccpav_ack_nonce; |
58 | u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN]; | 60 | u8 dccpav_buf[DCCP_MAX_ACKVEC_LEN]; |
@@ -75,9 +77,9 @@ struct dccp_ackvec_record { | |||
75 | struct list_head dccpavr_node; | 77 | struct list_head dccpavr_node; |
76 | u64 dccpavr_ack_seqno; | 78 | u64 dccpavr_ack_seqno; |
77 | u64 dccpavr_ack_ackno; | 79 | u64 dccpavr_ack_ackno; |
78 | u8 dccpavr_ack_ptr; | 80 | u16 dccpavr_ack_ptr; |
81 | u16 dccpavr_sent_len; | ||
79 | u8 dccpavr_ack_nonce; | 82 | u8 dccpavr_ack_nonce; |
80 | u8 dccpavr_sent_len; | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | struct sock; | 85 | struct sock; |
@@ -96,7 +98,8 @@ extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | |||
96 | extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, | 98 | extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, |
97 | struct sock *sk, const u64 ackno); | 99 | struct sock *sk, const u64 ackno); |
98 | extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | 100 | extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, |
99 | const u8 opt, const u8 *value, const u8 len); | 101 | u64 *ackno, const u8 opt, |
102 | const u8 *value, const u8 len); | ||
100 | 103 | ||
101 | extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); | 104 | extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); |
102 | 105 | ||
@@ -135,7 +138,8 @@ static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, | |||
135 | } | 138 | } |
136 | 139 | ||
137 | static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | 140 | static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, |
138 | const u8 opt, const u8 *value, const u8 len) | 141 | const u64 *ackno, const u8 opt, |
142 | const u8 *value, const u8 len) | ||
139 | { | 143 | { |
140 | return -1; | 144 | return -1; |
141 | } | 145 | } |
diff --git a/net/dccp/options.c b/net/dccp/options.c index ee709ae0a97f..f398b43bc055 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -62,6 +62,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
62 | struct dccp_sock *dp = dccp_sk(sk); | 62 | struct dccp_sock *dp = dccp_sk(sk); |
63 | const struct dccp_hdr *dh = dccp_hdr(skb); | 63 | const struct dccp_hdr *dh = dccp_hdr(skb); |
64 | const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; | 64 | const u8 pkt_type = DCCP_SKB_CB(skb)->dccpd_type; |
65 | u64 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; | ||
65 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); | 66 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); |
66 | unsigned char *opt_ptr = options; | 67 | unsigned char *opt_ptr = options; |
67 | const unsigned char *opt_end = (unsigned char *)dh + | 68 | const unsigned char *opt_end = (unsigned char *)dh + |
@@ -149,7 +150,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
149 | break; | 150 | break; |
150 | 151 | ||
151 | if (dccp_msk(sk)->dccpms_send_ack_vector && | 152 | if (dccp_msk(sk)->dccpms_send_ack_vector && |
152 | dccp_ackvec_parse(sk, skb, opt, value, len)) | 153 | dccp_ackvec_parse(sk, skb, &ackno, opt, value, len)) |
153 | goto out_invalid_option; | 154 | goto out_invalid_option; |
154 | break; | 155 | break; |
155 | case DCCPO_TIMESTAMP: | 156 | case DCCPO_TIMESTAMP: |