Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  net/dccp/ackvec.c
0004  *
0005  *  An implementation of Ack Vectors for the DCCP protocol
0006  *  Copyright (c) 2007 University of Aberdeen, Scotland, UK
0007  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
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  * dccp_ackvec_update_records  -  Record information about sent Ack Vectors
0047  * @av:     Ack Vector records to update
0048  * @seqno:  Sequence number of the packet carrying the Ack Vector just sent
0049  * @nonce_sum:  The sum of all buffer nonces contained in the Ack Vector
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      * When the buffer overflows, we keep no more than one record. This is
0066      * the simplest way of disambiguating sender-Acks dating from before the
0067      * overflow from sender-Acks which refer to after the overflow; a simple
0068      * solution is preferable here since we are handling an exception.
0069      */
0070     if (av->av_overflow)
0071         dccp_ackvec_purge_records(av);
0072     /*
0073      * Since GSS is incremented for each packet, the list is automatically
0074      * arranged in descending order of @ack_seqno.
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      * Exploit that records are inserted in descending order of sequence
0091      * number, start with the oldest record first. If @ackno is `before'
0092      * the earliest ack_ackno, the packet is too old to be considered.
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  * Buffer index and length computation using modulo-buffersize arithmetic.
0105  * Note that, as pointers move from right to left, head is `before' tail.
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  * dccp_ackvec_update_old  -  Update previous state as per RFC 4340, 11.4.1
0126  * @av:     non-empty buffer to update
0127  * @distance:   negative or zero distance of @seqno from buf_ackno downward
0128  * @seqno:  the (old) sequence number whose record is to be updated
0129  * @state:  state in which packet carrying @seqno was received
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              * Only update the state if packet has not been received
0146              * yet. This is OK as per the second table in RFC 4340,
0147              * 11.4.1; i.e. here we are using the following table:
0148              *                     RECEIVED
0149              *                      0   1   3
0150              *              S     +---+---+---+
0151              *              T   0 | 0 | 0 | 0 |
0152              *              O     +---+---+---+
0153              *              R   1 | 1 | 1 | 1 |
0154              *              E     +---+---+---+
0155              *              D   3 | 0 | 1 | 3 |
0156              *                    +---+---+---+
0157              * The "Not Received" state was set by reserve_seats().
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 /* Mark @num entries after buf_head as "Not yet received". */
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     /* check for buffer wrap-around */
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  * dccp_ackvec_add_new  -  Record one or more new entries in Ack Vector buffer
0191  * @av:      container of buffer to update (can be empty or non-empty)
0192  * @num_packets: number of packets to register (must be >= 1)
0193  * @seqno:   sequence number of the first packet in @num_packets
0194  * @state:   state in which packet carrying @seqno was received
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          * We received 1 packet and have a loss of size "num_packets-1"
0207          * which we squeeze into num_cells-1 rather than reserving an
0208          * entire byte for each lost packet.
0209          * The reason is that the vector grows in O(burst_length); when
0210          * it grows too large there will no room left for the payload.
0211          * This is a trade-off: if a few packets out of the burst show
0212          * up later, their state will not be changed; it is simply too
0213          * costly to reshuffle/reallocate/copy the buffer each time.
0214          * Should such problems persist, we will need to switch to a
0215          * different underlying data structure.
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  * dccp_ackvec_input  -  Register incoming packet in the buffer
0245  * @av: Ack Vector to register packet to
0246  * @skb: Packet to register
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  * dccp_ackvec_clear_state  -  Perform house-keeping / garbage-collection
0278  * @av: Ack Vector record to clean
0279  * @ackno: last Ack Vector which has been acknowledged
0280  *
0281  * This routine is called when the peer acknowledges the receipt of Ack Vectors
0282  * up to and including @ackno. While based on section A.3 of RFC 4340, here
0283  * are additional precautions to prevent corrupted buffer state. In particular,
0284  * we use tail_ackno to identify outdated records; it always marks the earliest
0285  * packet of group (2) in 11.4.2.
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      * Deal with outdated acknowledgments: this arises when e.g. there are
0298      * several old records and the acks from the peer come in slowly. In
0299      * that case we may still have records that pre-date tail_ackno.
0300      */
0301     delta = dccp_delta_seqno(av->av_tail_ackno, avr->avr_ack_ackno);
0302     if (delta < 0)
0303         goto free_records;
0304     /*
0305      * Deal with overlapping Ack Vectors: don't subtract more than the
0306      * number of packets between tail_ackno and ack_ackno.
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      * The run length of Ack Vector cells does not decrease over time. If
0313      * the run length is the same as at the time the Ack Vector was sent, we
0314      * free the ack_ptr cell. That cell can however not be freed if the run
0315      * length has increased: in this case we need to move the tail pointer
0316      * backwards (towards higher indices), to its next-oldest neighbour.
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         /* This move may not have cleared the overflow flag. */
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          * We have made sure that avr points to a valid cell within the
0330          * buffer. This cell is either older than head, or equals head
0331          * (empty buffer): in both cases we no longer have any overflow.
0332          */
0333         av->av_overflow = 0;
0334     }
0335 
0336     /*
0337      * The peer has acknowledged up to and including ack_ackno. Hence the
0338      * first packet in group (2) of 11.4.2 is the successor of ack_ackno.
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  *  Routines to keep track of Ack Vectors received in an skb
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 }