0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "dccp.h"
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <linux/export.h>
0013
0014 static struct kmem_cache *dccp_ackvec_slab;
0015 static struct kmem_cache *dccp_ackvec_record_slab;
0016
0017 struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority)
0018 {
0019 struct dccp_ackvec *av = kmem_cache_zalloc(dccp_ackvec_slab, priority);
0020
0021 if (av != NULL) {
0022 av->av_buf_head = av->av_buf_tail = DCCPAV_MAX_ACKVEC_LEN - 1;
0023 INIT_LIST_HEAD(&av->av_records);
0024 }
0025 return av;
0026 }
0027
0028 static void dccp_ackvec_purge_records(struct dccp_ackvec *av)
0029 {
0030 struct dccp_ackvec_record *cur, *next;
0031
0032 list_for_each_entry_safe(cur, next, &av->av_records, avr_node)
0033 kmem_cache_free(dccp_ackvec_record_slab, cur);
0034 INIT_LIST_HEAD(&av->av_records);
0035 }
0036
0037 void dccp_ackvec_free(struct dccp_ackvec *av)
0038 {
0039 if (likely(av != NULL)) {
0040 dccp_ackvec_purge_records(av);
0041 kmem_cache_free(dccp_ackvec_slab, av);
0042 }
0043 }
0044
0045
0046
0047
0048
0049
0050
0051 int dccp_ackvec_update_records(struct dccp_ackvec *av, u64 seqno, u8 nonce_sum)
0052 {
0053 struct dccp_ackvec_record *avr;
0054
0055 avr = kmem_cache_alloc(dccp_ackvec_record_slab, GFP_ATOMIC);
0056 if (avr == NULL)
0057 return -ENOBUFS;
0058
0059 avr->avr_ack_seqno = seqno;
0060 avr->avr_ack_ptr = av->av_buf_head;
0061 avr->avr_ack_ackno = av->av_buf_ackno;
0062 avr->avr_ack_nonce = nonce_sum;
0063 avr->avr_ack_runlen = dccp_ackvec_runlen(av->av_buf + av->av_buf_head);
0064
0065
0066
0067
0068
0069
0070 if (av->av_overflow)
0071 dccp_ackvec_purge_records(av);
0072
0073
0074
0075
0076 list_add(&avr->avr_node, &av->av_records);
0077
0078 dccp_pr_debug("Added Vector, ack_seqno=%llu, ack_ackno=%llu (rl=%u)\n",
0079 (unsigned long long)avr->avr_ack_seqno,
0080 (unsigned long long)avr->avr_ack_ackno,
0081 avr->avr_ack_runlen);
0082 return 0;
0083 }
0084
0085 static struct dccp_ackvec_record *dccp_ackvec_lookup(struct list_head *av_list,
0086 const u64 ackno)
0087 {
0088 struct dccp_ackvec_record *avr;
0089
0090
0091
0092
0093
0094 list_for_each_entry_reverse(avr, av_list, avr_node) {
0095 if (avr->avr_ack_seqno == ackno)
0096 return avr;
0097 if (before48(ackno, avr->avr_ack_seqno))
0098 break;
0099 }
0100 return NULL;
0101 }
0102
0103
0104
0105
0106
0107 static inline u16 __ackvec_idx_add(const u16 a, const u16 b)
0108 {
0109 return (a + b) % DCCPAV_MAX_ACKVEC_LEN;
0110 }
0111
0112 static inline u16 __ackvec_idx_sub(const u16 a, const u16 b)
0113 {
0114 return __ackvec_idx_add(a, DCCPAV_MAX_ACKVEC_LEN - b);
0115 }
0116
0117 u16 dccp_ackvec_buflen(const struct dccp_ackvec *av)
0118 {
0119 if (unlikely(av->av_overflow))
0120 return DCCPAV_MAX_ACKVEC_LEN;
0121 return __ackvec_idx_sub(av->av_buf_tail, av->av_buf_head);
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131 static void dccp_ackvec_update_old(struct dccp_ackvec *av, s64 distance,
0132 u64 seqno, enum dccp_ackvec_states state)
0133 {
0134 u16 ptr = av->av_buf_head;
0135
0136 BUG_ON(distance > 0);
0137 if (unlikely(dccp_ackvec_is_empty(av)))
0138 return;
0139
0140 do {
0141 u8 runlen = dccp_ackvec_runlen(av->av_buf + ptr);
0142
0143 if (distance + runlen >= 0) {
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 if (av->av_buf[ptr] == DCCPAV_NOT_RECEIVED)
0160 av->av_buf[ptr] = state;
0161 else
0162 dccp_pr_debug("Not changing %llu state to %u\n",
0163 (unsigned long long)seqno, state);
0164 break;
0165 }
0166
0167 distance += runlen + 1;
0168 ptr = __ackvec_idx_add(ptr, 1);
0169
0170 } while (ptr != av->av_buf_tail);
0171 }
0172
0173
0174 static void dccp_ackvec_reserve_seats(struct dccp_ackvec *av, u16 num)
0175 {
0176 u16 start = __ackvec_idx_add(av->av_buf_head, 1),
0177 len = DCCPAV_MAX_ACKVEC_LEN - start;
0178
0179
0180 if (num > len) {
0181 memset(av->av_buf + start, DCCPAV_NOT_RECEIVED, len);
0182 start = 0;
0183 num -= len;
0184 }
0185 if (num)
0186 memset(av->av_buf + start, DCCPAV_NOT_RECEIVED, num);
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196 static void dccp_ackvec_add_new(struct dccp_ackvec *av, u32 num_packets,
0197 u64 seqno, enum dccp_ackvec_states state)
0198 {
0199 u32 num_cells = num_packets;
0200
0201 if (num_packets > DCCPAV_BURST_THRESH) {
0202 u32 lost_packets = num_packets - 1;
0203
0204 DCCP_WARN("Warning: large burst loss (%u)\n", lost_packets);
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 for (num_packets = num_cells = 1; lost_packets; ++num_cells) {
0218 u8 len = min_t(u32, lost_packets, DCCPAV_MAX_RUNLEN);
0219
0220 av->av_buf_head = __ackvec_idx_sub(av->av_buf_head, 1);
0221 av->av_buf[av->av_buf_head] = DCCPAV_NOT_RECEIVED | len;
0222
0223 lost_packets -= len;
0224 }
0225 }
0226
0227 if (num_cells + dccp_ackvec_buflen(av) >= DCCPAV_MAX_ACKVEC_LEN) {
0228 DCCP_CRIT("Ack Vector buffer overflow: dropping old entries");
0229 av->av_overflow = true;
0230 }
0231
0232 av->av_buf_head = __ackvec_idx_sub(av->av_buf_head, num_packets);
0233 if (av->av_overflow)
0234 av->av_buf_tail = av->av_buf_head;
0235
0236 av->av_buf[av->av_buf_head] = state;
0237 av->av_buf_ackno = seqno;
0238
0239 if (num_packets > 1)
0240 dccp_ackvec_reserve_seats(av, num_packets - 1);
0241 }
0242
0243
0244
0245
0246
0247
0248 void dccp_ackvec_input(struct dccp_ackvec *av, struct sk_buff *skb)
0249 {
0250 u64 seqno = DCCP_SKB_CB(skb)->dccpd_seq;
0251 enum dccp_ackvec_states state = DCCPAV_RECEIVED;
0252
0253 if (dccp_ackvec_is_empty(av)) {
0254 dccp_ackvec_add_new(av, 1, seqno, state);
0255 av->av_tail_ackno = seqno;
0256
0257 } else {
0258 s64 num_packets = dccp_delta_seqno(av->av_buf_ackno, seqno);
0259 u8 *current_head = av->av_buf + av->av_buf_head;
0260
0261 if (num_packets == 1 &&
0262 dccp_ackvec_state(current_head) == state &&
0263 dccp_ackvec_runlen(current_head) < DCCPAV_MAX_RUNLEN) {
0264
0265 *current_head += 1;
0266 av->av_buf_ackno = seqno;
0267
0268 } else if (num_packets > 0) {
0269 dccp_ackvec_add_new(av, num_packets, seqno, state);
0270 } else {
0271 dccp_ackvec_update_old(av, num_packets, seqno, state);
0272 }
0273 }
0274 }
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 void dccp_ackvec_clear_state(struct dccp_ackvec *av, const u64 ackno)
0288 {
0289 struct dccp_ackvec_record *avr, *next;
0290 u8 runlen_now, eff_runlen;
0291 s64 delta;
0292
0293 avr = dccp_ackvec_lookup(&av->av_records, ackno);
0294 if (avr == NULL)
0295 return;
0296
0297
0298
0299
0300
0301 delta = dccp_delta_seqno(av->av_tail_ackno, avr->avr_ack_ackno);
0302 if (delta < 0)
0303 goto free_records;
0304
0305
0306
0307
0308 eff_runlen = delta < avr->avr_ack_runlen ? delta : avr->avr_ack_runlen;
0309
0310 runlen_now = dccp_ackvec_runlen(av->av_buf + avr->avr_ack_ptr);
0311
0312
0313
0314
0315
0316
0317
0318 if (runlen_now > eff_runlen) {
0319
0320 av->av_buf[avr->avr_ack_ptr] -= eff_runlen + 1;
0321 av->av_buf_tail = __ackvec_idx_add(avr->avr_ack_ptr, 1);
0322
0323
0324 if (av->av_overflow)
0325 av->av_overflow = (av->av_buf_head == av->av_buf_tail);
0326 } else {
0327 av->av_buf_tail = avr->avr_ack_ptr;
0328
0329
0330
0331
0332
0333 av->av_overflow = 0;
0334 }
0335
0336
0337
0338
0339
0340 av->av_tail_ackno = ADD48(avr->avr_ack_ackno, 1);
0341
0342 free_records:
0343 list_for_each_entry_safe_from(avr, next, &av->av_records, avr_node) {
0344 list_del(&avr->avr_node);
0345 kmem_cache_free(dccp_ackvec_record_slab, avr);
0346 }
0347 }
0348
0349
0350
0351
0352 int dccp_ackvec_parsed_add(struct list_head *head, u8 *vec, u8 len, u8 nonce)
0353 {
0354 struct dccp_ackvec_parsed *new = kmalloc(sizeof(*new), GFP_ATOMIC);
0355
0356 if (new == NULL)
0357 return -ENOBUFS;
0358 new->vec = vec;
0359 new->len = len;
0360 new->nonce = nonce;
0361
0362 list_add_tail(&new->node, head);
0363 return 0;
0364 }
0365 EXPORT_SYMBOL_GPL(dccp_ackvec_parsed_add);
0366
0367 void dccp_ackvec_parsed_cleanup(struct list_head *parsed_chunks)
0368 {
0369 struct dccp_ackvec_parsed *cur, *next;
0370
0371 list_for_each_entry_safe(cur, next, parsed_chunks, node)
0372 kfree(cur);
0373 INIT_LIST_HEAD(parsed_chunks);
0374 }
0375 EXPORT_SYMBOL_GPL(dccp_ackvec_parsed_cleanup);
0376
0377 int __init dccp_ackvec_init(void)
0378 {
0379 dccp_ackvec_slab = kmem_cache_create("dccp_ackvec",
0380 sizeof(struct dccp_ackvec), 0,
0381 SLAB_HWCACHE_ALIGN, NULL);
0382 if (dccp_ackvec_slab == NULL)
0383 goto out_err;
0384
0385 dccp_ackvec_record_slab = kmem_cache_create("dccp_ackvec_record",
0386 sizeof(struct dccp_ackvec_record),
0387 0, SLAB_HWCACHE_ALIGN, NULL);
0388 if (dccp_ackvec_record_slab == NULL)
0389 goto out_destroy_slab;
0390
0391 return 0;
0392
0393 out_destroy_slab:
0394 kmem_cache_destroy(dccp_ackvec_slab);
0395 dccp_ackvec_slab = NULL;
0396 out_err:
0397 DCCP_CRIT("Unable to create Ack Vector slab cache");
0398 return -ENOBUFS;
0399 }
0400
0401 void dccp_ackvec_exit(void)
0402 {
0403 kmem_cache_destroy(dccp_ackvec_slab);
0404 dccp_ackvec_slab = NULL;
0405 kmem_cache_destroy(dccp_ackvec_record_slab);
0406 dccp_ackvec_record_slab = NULL;
0407 }