linux/include/net/inet_frag.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __NET_FRAG_H__
   3#define __NET_FRAG_H__
   4
   5#include <linux/rhashtable-types.h>
   6
   7struct netns_frags {
   8        /* sysctls */
   9        long                    high_thresh;
  10        long                    low_thresh;
  11        int                     timeout;
  12        int                     max_dist;
  13        struct inet_frags       *f;
  14
  15        struct rhashtable       rhashtable ____cacheline_aligned_in_smp;
  16
  17        /* Keep atomic mem on separate cachelines in structs that include it */
  18        atomic_long_t           mem ____cacheline_aligned_in_smp;
  19};
  20
  21/**
  22 * fragment queue flags
  23 *
  24 * @INET_FRAG_FIRST_IN: first fragment has arrived
  25 * @INET_FRAG_LAST_IN: final fragment has arrived
  26 * @INET_FRAG_COMPLETE: frag queue has been processed and is due for destruction
  27 */
  28enum {
  29        INET_FRAG_FIRST_IN      = BIT(0),
  30        INET_FRAG_LAST_IN       = BIT(1),
  31        INET_FRAG_COMPLETE      = BIT(2),
  32};
  33
  34struct frag_v4_compare_key {
  35        __be32          saddr;
  36        __be32          daddr;
  37        u32             user;
  38        u32             vif;
  39        __be16          id;
  40        u16             protocol;
  41};
  42
  43struct frag_v6_compare_key {
  44        struct in6_addr saddr;
  45        struct in6_addr daddr;
  46        u32             user;
  47        __be32          id;
  48        u32             iif;
  49};
  50
  51/**
  52 * struct inet_frag_queue - fragment queue
  53 *
  54 * @node: rhash node
  55 * @key: keys identifying this frag.
  56 * @timer: queue expiration timer
  57 * @lock: spinlock protecting this frag
  58 * @refcnt: reference count of the queue
  59 * @rb_fragments: received fragments rb-tree root
  60 * @fragments_tail: received fragments tail
  61 * @last_run_head: the head of the last "run". see ip_fragment.c
  62 * @stamp: timestamp of the last received fragment
  63 * @len: total length of the original datagram
  64 * @meat: length of received fragments so far
  65 * @flags: fragment queue flags
  66 * @max_size: maximum received fragment size
  67 * @net: namespace that this frag belongs to
  68 * @rcu: rcu head for freeing deferall
  69 */
  70struct inet_frag_queue {
  71        struct rhash_head       node;
  72        union {
  73                struct frag_v4_compare_key v4;
  74                struct frag_v6_compare_key v6;
  75        } key;
  76        struct timer_list       timer;
  77        spinlock_t              lock;
  78        refcount_t              refcnt;
  79        struct rb_root          rb_fragments;
  80        struct sk_buff          *fragments_tail;
  81        struct sk_buff          *last_run_head;
  82        ktime_t                 stamp;
  83        int                     len;
  84        int                     meat;
  85        __u8                    flags;
  86        u16                     max_size;
  87        struct netns_frags      *net;
  88        struct rcu_head         rcu;
  89};
  90
  91struct inet_frags {
  92        unsigned int            qsize;
  93
  94        void                    (*constructor)(struct inet_frag_queue *q,
  95                                               const void *arg);
  96        void                    (*destructor)(struct inet_frag_queue *);
  97        void                    (*frag_expire)(struct timer_list *t);
  98        struct kmem_cache       *frags_cachep;
  99        const char              *frags_cache_name;
 100        struct rhashtable_params rhash_params;
 101};
 102
 103int inet_frags_init(struct inet_frags *);
 104void inet_frags_fini(struct inet_frags *);
 105
 106static inline int inet_frags_init_net(struct netns_frags *nf)
 107{
 108        atomic_long_set(&nf->mem, 0);
 109        return rhashtable_init(&nf->rhashtable, &nf->f->rhash_params);
 110}
 111void inet_frags_exit_net(struct netns_frags *nf);
 112
 113void inet_frag_kill(struct inet_frag_queue *q);
 114void inet_frag_destroy(struct inet_frag_queue *q);
 115struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, void *key);
 116
 117/* Free all skbs in the queue; return the sum of their truesizes. */
 118unsigned int inet_frag_rbtree_purge(struct rb_root *root);
 119
 120static inline void inet_frag_put(struct inet_frag_queue *q)
 121{
 122        if (refcount_dec_and_test(&q->refcnt))
 123                inet_frag_destroy(q);
 124}
 125
 126/* Memory Tracking Functions. */
 127
 128static inline long frag_mem_limit(const struct netns_frags *nf)
 129{
 130        return atomic_long_read(&nf->mem);
 131}
 132
 133static inline void sub_frag_mem_limit(struct netns_frags *nf, long val)
 134{
 135        atomic_long_sub(val, &nf->mem);
 136}
 137
 138static inline void add_frag_mem_limit(struct netns_frags *nf, long val)
 139{
 140        atomic_long_add(val, &nf->mem);
 141}
 142
 143/* RFC 3168 support :
 144 * We want to check ECN values of all fragments, do detect invalid combinations.
 145 * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
 146 */
 147#define IPFRAG_ECN_NOT_ECT      0x01 /* one frag had ECN_NOT_ECT */
 148#define IPFRAG_ECN_ECT_1        0x02 /* one frag had ECN_ECT_1 */
 149#define IPFRAG_ECN_ECT_0        0x04 /* one frag had ECN_ECT_0 */
 150#define IPFRAG_ECN_CE           0x08 /* one frag had ECN_CE */
 151
 152extern const u8 ip_frag_ecn_table[16];
 153
 154/* Return values of inet_frag_queue_insert() */
 155#define IPFRAG_OK       0
 156#define IPFRAG_DUP      1
 157#define IPFRAG_OVERLAP  2
 158int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
 159                           int offset, int end);
 160void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
 161                              struct sk_buff *parent);
 162void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
 163                            void *reasm_data);
 164struct sk_buff *inet_frag_pull_head(struct inet_frag_queue *q);
 165
 166#endif
 167