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 | ff49e27089ec363b7fc3849504e0435d447ab18a (patch) | |
tree | eb6f7d4ec829f2c0ca206c0769c15c08e592743c /net/dccp/ackvec.c | |
parent | b8c6bcee1dbc1aadcd67af998e414e73fa166a7d (diff) |
dccp ccid-2: Ack Vector interface clean-up
This patch brings the Ack Vector interface up to date. Its main purpose is
to lay the basis for the subsequent patches of this set, which will use the
new data structure fields and routines.
There are no real algorithmic changes, rather an adaptation:
(1) Replaced the static Ack Vector size (2) with a #define so that it can
be adapted (with low loss / Ack Ratio, a value of 1 works, so 2 seems
to be sufficient for the moment) and added a solution so that computing
the ECN nonce will continue to work - even with larger Ack Vectors.
(2) Replaced the #defines for Ack Vector states with a complete enum.
(3) Replaced #defines to compute Ack Vector length and state with general
purpose routines (inlines), and updated code to use these.
(4) Added a `tail' field (conversion to circular buffer in subsequent patch).
(5) Updated the (outdated) documentation for Ack Vector struct.
(6) All sequence number containers now trimmed to 48 bits.
(7) Removal of unused bits:
* removed dccpav_ack_nonce from struct dccp_ackvec, since this is already
redundantly stored in the `dccpavr_ack_nonce' (of Ack Vector record);
* removed Elapsed Time for Ack Vectors (it was nowhere used);
* replaced semantics of dccpavr_sent_len with dccpavr_ack_runlen, since
the code needs to be able to remember the old run length;
* reduced the de-/allocation routines (redundant / duplicate tests).
Justification for removing Elapsed Time information [can be removed]:
---------------------------------------------------------------------
1. The Elapsed Time information for Ack Vectors was nowhere used in the code.
2. DCCP does not implement rate-based pacing of acknowledgments. The only
recommendation for always including Elapsed Time is in section 11.3 of
RFC 4340: "Receivers that rate-pace acknowledgements SHOULD [...]
include Elapsed Time options". But such is not the case here.
3. It does not really improve estimation accuracy. The Elapsed Time field only
records the time between the arrival of the last acknowledgeable packet and
the time the Ack Vector is sent out. Since Linux does not (yet) implement
delayed Acks, the time difference will typically be small, since often the
arrival of a data packet triggers sending feedback at the HC-receiver.
Justification for changes in de-/allocation routines [can be removed]:
----------------------------------------------------------------------
* INIT_LIST_HEAD in dccp_ackvec_record_new was redundant, since the list
pointers were later overwritten when the node was added via list_add();
* dccp_ackvec_record_new() was called in a single place only;
* calls to list_del_init() before calling dccp_ackvec_record_delete() were
redundant, since subsequently the entire element was k-freed;
* since all calls to dccp_ackvec_record_delete() were preceded to a call to
list_del_init(), the WARN_ON test would never evaluate to true;
* since all calls to dccp_ackvec_record_delete() were made from within
list_for_each_entry_safe(), the test for avr == NULL was redundant;
* list_empty() in ackvec_free was redundant, since the same condition is
embedded in the loop condition of the subsequent list_for_each_entry_safe().
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp/ackvec.c')
-rw-r--r-- | net/dccp/ackvec.c | 178 |
1 files changed, 64 insertions, 114 deletions
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index 01e4d39fa232..85ad70cfba5b 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/ackvec.c | 2 | * net/dccp/ackvec.c |
3 | * | 3 | * |
4 | * An implementation of the DCCP protocol | 4 | * An implementation of Ack Vectors for the DCCP protocol |
5 | * Copyright (c) 2007 University of Aberdeen, Scotland, UK | ||
5 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> |
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -23,24 +24,32 @@ | |||
23 | static struct kmem_cache *dccp_ackvec_slab; | 24 | static struct kmem_cache *dccp_ackvec_slab; |
24 | static struct kmem_cache *dccp_ackvec_record_slab; | 25 | static struct kmem_cache *dccp_ackvec_record_slab; |
25 | 26 | ||
26 | static struct dccp_ackvec_record *dccp_ackvec_record_new(void) | 27 | struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) |
27 | { | 28 | { |
28 | struct dccp_ackvec_record *avr = | 29 | struct dccp_ackvec *av = kmem_cache_zalloc(dccp_ackvec_slab, priority); |
29 | kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC); | 30 | |
31 | if (av != NULL) { | ||
32 | av->av_buf_head = DCCPAV_MAX_ACKVEC_LEN - 1; | ||
33 | INIT_LIST_HEAD(&av->av_records); | ||
34 | } | ||
35 | return av; | ||
36 | } | ||
30 | 37 | ||
31 | if (avr != NULL) | 38 | static void dccp_ackvec_purge_records(struct dccp_ackvec *av) |
32 | INIT_LIST_HEAD(&avr->avr_node); | 39 | { |
40 | struct dccp_ackvec_record *cur, *next; | ||
33 | 41 | ||
34 | return avr; | 42 | list_for_each_entry_safe(cur, next, &av->av_records, avr_node) |
43 | kmem_cache_free(dccp_ackvec_record_slab, cur); | ||
44 | INIT_LIST_HEAD(&av->av_records); | ||
35 | } | 45 | } |
36 | 46 | ||
37 | static void dccp_ackvec_record_delete(struct dccp_ackvec_record *avr) | 47 | void dccp_ackvec_free(struct dccp_ackvec *av) |
38 | { | 48 | { |
39 | if (unlikely(avr == NULL)) | 49 | if (likely(av != NULL)) { |
40 | return; | 50 | dccp_ackvec_purge_records(av); |
41 | /* Check if deleting a linked record */ | 51 | kmem_cache_free(dccp_ackvec_slab, av); |
42 | WARN_ON(!list_empty(&avr->avr_node)); | 52 | } |
43 | kmem_cache_free(dccp_ackvec_record_slab, avr); | ||
44 | } | 53 | } |
45 | 54 | ||
46 | static void dccp_ackvec_insert_avr(struct dccp_ackvec *av, | 55 | static void dccp_ackvec_insert_avr(struct dccp_ackvec *av, |
@@ -68,24 +77,16 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
68 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | 77 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; |
69 | /* Figure out how many options do we need to represent the ackvec */ | 78 | /* Figure out how many options do we need to represent the ackvec */ |
70 | const u8 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_SINGLE_OPT_MAXLEN); | 79 | const u8 nr_opts = DIV_ROUND_UP(av->av_vec_len, DCCP_SINGLE_OPT_MAXLEN); |
71 | u16 len = av->av_vec_len + 2 * nr_opts, i; | 80 | u16 len = av->av_vec_len + 2 * nr_opts; |
72 | u32 elapsed_time; | 81 | u8 i, nonce = 0; |
73 | const unsigned char *tail, *from; | 82 | const unsigned char *tail, *from; |
74 | unsigned char *to; | 83 | unsigned char *to; |
75 | struct dccp_ackvec_record *avr; | 84 | struct dccp_ackvec_record *avr; |
76 | suseconds_t delta; | ||
77 | 85 | ||
78 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) | 86 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) |
79 | return -1; | 87 | return -1; |
80 | 88 | ||
81 | delta = ktime_us_delta(ktime_get_real(), av->av_time); | 89 | avr = kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC); |
82 | elapsed_time = delta / 10; | ||
83 | |||
84 | if (elapsed_time != 0 && | ||
85 | dccp_insert_option_elapsed_time(sk, skb, elapsed_time)) | ||
86 | return -1; | ||
87 | |||
88 | avr = dccp_ackvec_record_new(); | ||
89 | if (avr == NULL) | 90 | if (avr == NULL) |
90 | return -1; | 91 | return -1; |
91 | 92 | ||
@@ -94,7 +95,7 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
94 | to = skb_push(skb, len); | 95 | to = skb_push(skb, len); |
95 | len = av->av_vec_len; | 96 | len = av->av_vec_len; |
96 | from = av->av_buf + av->av_buf_head; | 97 | from = av->av_buf + av->av_buf_head; |
97 | tail = av->av_buf + DCCP_MAX_ACKVEC_LEN; | 98 | tail = av->av_buf + DCCPAV_MAX_ACKVEC_LEN; |
98 | 99 | ||
99 | for (i = 0; i < nr_opts; ++i) { | 100 | for (i = 0; i < nr_opts; ++i) { |
100 | int copylen = len; | 101 | int copylen = len; |
@@ -102,7 +103,13 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
102 | if (len > DCCP_SINGLE_OPT_MAXLEN) | 103 | if (len > DCCP_SINGLE_OPT_MAXLEN) |
103 | copylen = DCCP_SINGLE_OPT_MAXLEN; | 104 | copylen = DCCP_SINGLE_OPT_MAXLEN; |
104 | 105 | ||
105 | *to++ = DCCPO_ACK_VECTOR_0; | 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]; | ||
106 | *to++ = copylen + 2; | 113 | *to++ = copylen + 2; |
107 | 114 | ||
108 | /* Check if buf_head wraps */ | 115 | /* Check if buf_head wraps */ |
@@ -123,75 +130,24 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | |||
123 | } | 130 | } |
124 | 131 | ||
125 | /* | 132 | /* |
126 | * From RFC 4340, A.2: | 133 | * Each sent Ack Vector is recorded in the list, as per A.2 of RFC 4340. |
127 | * | ||
128 | * For each acknowledgement it sends, the HC-Receiver will add an | ||
129 | * acknowledgement record. ack_seqno will equal the HC-Receiver | ||
130 | * sequence number it used for the ack packet; ack_ptr will equal | ||
131 | * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will | ||
132 | * equal buf_nonce. | ||
133 | */ | 134 | */ |
134 | avr->avr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; | 135 | avr->avr_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; |
135 | avr->avr_ack_ptr = av->av_buf_head; | 136 | avr->avr_ack_ptr = av->av_buf_head; |
136 | avr->avr_ack_ackno = av->av_buf_ackno; | 137 | avr->avr_ack_ackno = av->av_buf_ackno; |
137 | avr->avr_ack_nonce = av->av_buf_nonce; | 138 | avr->avr_ack_nonce = nonce; |
138 | avr->avr_sent_len = av->av_vec_len; | 139 | avr->avr_ack_runlen = dccp_ackvec_runlen(av->av_buf + av->av_buf_head); |
139 | 140 | ||
140 | dccp_ackvec_insert_avr(av, avr); | 141 | dccp_ackvec_insert_avr(av, avr); |
141 | 142 | ||
142 | dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, " | 143 | dccp_pr_debug("%s ACK Vector 0, len=%d, ack_seqno=%llu, " |
143 | "ack_ackno=%llu\n", | 144 | "ack_ackno=%llu\n", |
144 | dccp_role(sk), avr->avr_sent_len, | 145 | dccp_role(sk), avr->avr_ack_runlen, |
145 | (unsigned long long)avr->avr_ack_seqno, | 146 | (unsigned long long)avr->avr_ack_seqno, |
146 | (unsigned long long)avr->avr_ack_ackno); | 147 | (unsigned long long)avr->avr_ack_ackno); |
147 | return 0; | 148 | return 0; |
148 | } | 149 | } |
149 | 150 | ||
150 | struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) | ||
151 | { | ||
152 | struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority); | ||
153 | |||
154 | if (av != NULL) { | ||
155 | av->av_buf_head = DCCP_MAX_ACKVEC_LEN - 1; | ||
156 | av->av_buf_ackno = UINT48_MAX + 1; | ||
157 | av->av_buf_nonce = 0; | ||
158 | av->av_time = ktime_set(0, 0); | ||
159 | av->av_vec_len = 0; | ||
160 | INIT_LIST_HEAD(&av->av_records); | ||
161 | } | ||
162 | |||
163 | return av; | ||
164 | } | ||
165 | |||
166 | void dccp_ackvec_free(struct dccp_ackvec *av) | ||
167 | { | ||
168 | if (unlikely(av == NULL)) | ||
169 | return; | ||
170 | |||
171 | if (!list_empty(&av->av_records)) { | ||
172 | struct dccp_ackvec_record *avr, *next; | ||
173 | |||
174 | list_for_each_entry_safe(avr, next, &av->av_records, avr_node) { | ||
175 | list_del_init(&avr->avr_node); | ||
176 | dccp_ackvec_record_delete(avr); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | kmem_cache_free(dccp_ackvec_slab, av); | ||
181 | } | ||
182 | |||
183 | static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, | ||
184 | const u32 index) | ||
185 | { | ||
186 | return av->av_buf[index] & DCCP_ACKVEC_STATE_MASK; | ||
187 | } | ||
188 | |||
189 | static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, | ||
190 | const u32 index) | ||
191 | { | ||
192 | return av->av_buf[index] & DCCP_ACKVEC_LEN_MASK; | ||
193 | } | ||
194 | |||
195 | /* | 151 | /* |
196 | * If several packets are missing, the HC-Receiver may prefer to enter multiple | 152 | * If several packets are missing, the HC-Receiver may prefer to enter multiple |
197 | * bytes with run length 0, rather than a single byte with a larger run length; | 153 | * bytes with run length 0, rather than a single byte with a larger run length; |
@@ -204,7 +160,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, | |||
204 | unsigned int gap; | 160 | unsigned int gap; |
205 | long new_head; | 161 | long new_head; |
206 | 162 | ||
207 | if (av->av_vec_len + packets > DCCP_MAX_ACKVEC_LEN) | 163 | if (av->av_vec_len + packets > DCCPAV_MAX_ACKVEC_LEN) |
208 | return -ENOBUFS; | 164 | return -ENOBUFS; |
209 | 165 | ||
210 | gap = packets - 1; | 166 | gap = packets - 1; |
@@ -212,18 +168,18 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, | |||
212 | 168 | ||
213 | if (new_head < 0) { | 169 | if (new_head < 0) { |
214 | if (gap > 0) { | 170 | if (gap > 0) { |
215 | memset(av->av_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED, | 171 | memset(av->av_buf, DCCPAV_NOT_RECEIVED, |
216 | gap + new_head + 1); | 172 | gap + new_head + 1); |
217 | gap = -new_head; | 173 | gap = -new_head; |
218 | } | 174 | } |
219 | new_head += DCCP_MAX_ACKVEC_LEN; | 175 | new_head += DCCPAV_MAX_ACKVEC_LEN; |
220 | } | 176 | } |
221 | 177 | ||
222 | av->av_buf_head = new_head; | 178 | av->av_buf_head = new_head; |
223 | 179 | ||
224 | if (gap > 0) | 180 | if (gap > 0) |
225 | memset(av->av_buf + av->av_buf_head + 1, | 181 | memset(av->av_buf + av->av_buf_head + 1, |
226 | DCCP_ACKVEC_STATE_NOT_RECEIVED, gap); | 182 | DCCPAV_NOT_RECEIVED, gap); |
227 | 183 | ||
228 | av->av_buf[av->av_buf_head] = state; | 184 | av->av_buf[av->av_buf_head] = state; |
229 | av->av_vec_len += packets; | 185 | av->av_vec_len += packets; |
@@ -236,6 +192,8 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, | |||
236 | int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | 192 | int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, |
237 | const u64 ackno, const u8 state) | 193 | const u64 ackno, const u8 state) |
238 | { | 194 | { |
195 | u8 *cur_head = av->av_buf + av->av_buf_head, | ||
196 | *buf_end = av->av_buf + DCCPAV_MAX_ACKVEC_LEN; | ||
239 | /* | 197 | /* |
240 | * Check at the right places if the buffer is full, if it is, tell the | 198 | * Check at the right places if the buffer is full, if it is, tell the |
241 | * caller to start dropping packets till the HC-Sender acks our ACK | 199 | * caller to start dropping packets till the HC-Sender acks our ACK |
@@ -260,7 +218,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | |||
260 | 218 | ||
261 | /* See if this is the first ackno being inserted */ | 219 | /* See if this is the first ackno being inserted */ |
262 | if (av->av_vec_len == 0) { | 220 | if (av->av_vec_len == 0) { |
263 | av->av_buf[av->av_buf_head] = state; | 221 | *cur_head = state; |
264 | av->av_vec_len = 1; | 222 | av->av_vec_len = 1; |
265 | } else if (after48(ackno, av->av_buf_ackno)) { | 223 | } else if (after48(ackno, av->av_buf_ackno)) { |
266 | const u64 delta = dccp_delta_seqno(av->av_buf_ackno, ackno); | 224 | const u64 delta = dccp_delta_seqno(av->av_buf_ackno, ackno); |
@@ -269,10 +227,9 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | |||
269 | * Look if the state of this packet is the same as the | 227 | * Look if the state of this packet is the same as the |
270 | * previous ackno and if so if we can bump the head len. | 228 | * previous ackno and if so if we can bump the head len. |
271 | */ | 229 | */ |
272 | if (delta == 1 && | 230 | if (delta == 1 && dccp_ackvec_state(cur_head) == state && |
273 | dccp_ackvec_state(av, av->av_buf_head) == state && | 231 | dccp_ackvec_runlen(cur_head) < DCCPAV_MAX_RUNLEN) |
274 | dccp_ackvec_len(av, av->av_buf_head) < DCCP_ACKVEC_LEN_MASK) | 232 | *cur_head += 1; |
275 | av->av_buf[av->av_buf_head]++; | ||
276 | else if (dccp_ackvec_set_buf_head_state(av, delta, state)) | 233 | else if (dccp_ackvec_set_buf_head_state(av, delta, state)) |
277 | return -ENOBUFS; | 234 | return -ENOBUFS; |
278 | } else { | 235 | } else { |
@@ -285,21 +242,17 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | |||
285 | * could reduce the complexity of this scan.) | 242 | * could reduce the complexity of this scan.) |
286 | */ | 243 | */ |
287 | u64 delta = dccp_delta_seqno(ackno, av->av_buf_ackno); | 244 | u64 delta = dccp_delta_seqno(ackno, av->av_buf_ackno); |
288 | u32 index = av->av_buf_head; | ||
289 | 245 | ||
290 | while (1) { | 246 | while (1) { |
291 | const u8 len = dccp_ackvec_len(av, index); | 247 | const u8 len = dccp_ackvec_runlen(cur_head); |
292 | const u8 av_state = dccp_ackvec_state(av, index); | ||
293 | /* | 248 | /* |
294 | * valid packets not yet in av_buf have a reserved | 249 | * valid packets not yet in av_buf have a reserved |
295 | * entry, with a len equal to 0. | 250 | * entry, with a len equal to 0. |
296 | */ | 251 | */ |
297 | if (av_state == DCCP_ACKVEC_STATE_NOT_RECEIVED && | 252 | if (*cur_head == DCCPAV_NOT_RECEIVED && delta == 0) { |
298 | len == 0 && delta == 0) { /* Found our | ||
299 | reserved seat! */ | ||
300 | dccp_pr_debug("Found %llu reserved seat!\n", | 253 | dccp_pr_debug("Found %llu reserved seat!\n", |
301 | (unsigned long long)ackno); | 254 | (unsigned long long)ackno); |
302 | av->av_buf[index] = state; | 255 | *cur_head = state; |
303 | goto out; | 256 | goto out; |
304 | } | 257 | } |
305 | /* len == 0 means one packet */ | 258 | /* len == 0 means one packet */ |
@@ -307,13 +260,12 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | |||
307 | goto out_duplicate; | 260 | goto out_duplicate; |
308 | 261 | ||
309 | delta -= len + 1; | 262 | delta -= len + 1; |
310 | if (++index == DCCP_MAX_ACKVEC_LEN) | 263 | if (++cur_head == buf_end) |
311 | index = 0; | 264 | cur_head = av->av_buf; |
312 | } | 265 | } |
313 | } | 266 | } |
314 | 267 | ||
315 | av->av_buf_ackno = ackno; | 268 | av->av_buf_ackno = ackno; |
316 | av->av_time = ktime_get_real(); | ||
317 | out: | 269 | out: |
318 | return 0; | 270 | return 0; |
319 | 271 | ||
@@ -333,13 +285,13 @@ static void dccp_ackvec_throw_record(struct dccp_ackvec *av, | |||
333 | if (av->av_buf_head <= avr->avr_ack_ptr) | 285 | if (av->av_buf_head <= avr->avr_ack_ptr) |
334 | av->av_vec_len = avr->avr_ack_ptr - av->av_buf_head; | 286 | av->av_vec_len = avr->avr_ack_ptr - av->av_buf_head; |
335 | else | 287 | else |
336 | av->av_vec_len = DCCP_MAX_ACKVEC_LEN - 1 - | 288 | av->av_vec_len = DCCPAV_MAX_ACKVEC_LEN - 1 - |
337 | av->av_buf_head + avr->avr_ack_ptr; | 289 | av->av_buf_head + avr->avr_ack_ptr; |
338 | 290 | ||
339 | /* free records */ | 291 | /* free records */ |
340 | list_for_each_entry_safe_from(avr, next, &av->av_records, avr_node) { | 292 | list_for_each_entry_safe_from(avr, next, &av->av_records, avr_node) { |
341 | list_del_init(&avr->avr_node); | 293 | list_del(&avr->avr_node); |
342 | dccp_ackvec_record_delete(avr); | 294 | kmem_cache_free(dccp_ackvec_record_slab, avr); |
343 | } | 295 | } |
344 | } | 296 | } |
345 | 297 | ||
@@ -357,7 +309,7 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, | |||
357 | if (ackno == avr->avr_ack_seqno) { | 309 | if (ackno == avr->avr_ack_seqno) { |
358 | dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, " | 310 | dccp_pr_debug("%s ACK packet 0, len=%d, ack_seqno=%llu, " |
359 | "ack_ackno=%llu, ACKED!\n", | 311 | "ack_ackno=%llu, ACKED!\n", |
360 | dccp_role(sk), 1, | 312 | dccp_role(sk), avr->avr_ack_runlen, |
361 | (unsigned long long)avr->avr_ack_seqno, | 313 | (unsigned long long)avr->avr_ack_seqno, |
362 | (unsigned long long)avr->avr_ack_ackno); | 314 | (unsigned long long)avr->avr_ack_ackno); |
363 | dccp_ackvec_throw_record(av, avr); | 315 | dccp_ackvec_throw_record(av, avr); |
@@ -387,7 +339,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | |||
387 | */ | 339 | */ |
388 | avr = list_entry(av->av_records.next, struct dccp_ackvec_record, avr_node); | 340 | avr = list_entry(av->av_records.next, struct dccp_ackvec_record, avr_node); |
389 | while (i--) { | 341 | while (i--) { |
390 | const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; | 342 | const u8 rl = dccp_ackvec_runlen(vector); |
391 | u64 ackno_end_rl; | 343 | u64 ackno_end_rl; |
392 | 344 | ||
393 | dccp_set_seqno(&ackno_end_rl, *ackno - rl); | 345 | dccp_set_seqno(&ackno_end_rl, *ackno - rl); |
@@ -404,8 +356,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | |||
404 | break; | 356 | break; |
405 | found: | 357 | found: |
406 | if (between48(avr->avr_ack_seqno, ackno_end_rl, *ackno)) { | 358 | if (between48(avr->avr_ack_seqno, ackno_end_rl, *ackno)) { |
407 | const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; | 359 | if (dccp_ackvec_state(vector) != DCCPAV_NOT_RECEIVED) { |
408 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { | ||
409 | dccp_pr_debug("%s ACK vector 0, len=%d, " | 360 | dccp_pr_debug("%s ACK vector 0, len=%d, " |
410 | "ack_seqno=%llu, ack_ackno=%llu, " | 361 | "ack_seqno=%llu, ack_ackno=%llu, " |
411 | "ACKED!\n", | 362 | "ACKED!\n", |
@@ -448,10 +399,9 @@ int __init dccp_ackvec_init(void) | |||
448 | if (dccp_ackvec_slab == NULL) | 399 | if (dccp_ackvec_slab == NULL) |
449 | goto out_err; | 400 | goto out_err; |
450 | 401 | ||
451 | dccp_ackvec_record_slab = | 402 | dccp_ackvec_record_slab = kmem_cache_create("dccp_ackvec_record", |
452 | kmem_cache_create("dccp_ackvec_record", | 403 | sizeof(struct dccp_ackvec_record), |
453 | sizeof(struct dccp_ackvec_record), | 404 | 0, SLAB_HWCACHE_ALIGN, NULL); |
454 | 0, SLAB_HWCACHE_ALIGN, NULL); | ||
455 | if (dccp_ackvec_record_slab == NULL) | 405 | if (dccp_ackvec_record_slab == NULL) |
456 | goto out_destroy_slab; | 406 | goto out_destroy_slab; |
457 | 407 | ||