linux/include/net/inet_frag.h
<<
>>
Prefs
   1#ifndef __NET_FRAG_H__
   2#define __NET_FRAG_H__
   3
   4#include <linux/percpu_counter.h>
   5
   6struct netns_frags {
   7        /* The percpu_counter "mem" need to be cacheline aligned.
   8         *  mem.count must not share cacheline with other writers
   9         */
  10        struct percpu_counter   mem ____cacheline_aligned_in_smp;
  11
  12        /* sysctls */
  13        int                     timeout;
  14        int                     high_thresh;
  15        int                     low_thresh;
  16        int                     max_dist;
  17};
  18
  19/**
  20 * fragment queue flags
  21 *
  22 * @INET_FRAG_FIRST_IN: first fragment has arrived
  23 * @INET_FRAG_LAST_IN: final fragment has arrived
  24 * @INET_FRAG_COMPLETE: frag queue has been processed and is due for destruction
  25 */
  26enum {
  27        INET_FRAG_FIRST_IN      = BIT(0),
  28        INET_FRAG_LAST_IN       = BIT(1),
  29        INET_FRAG_COMPLETE      = BIT(2),
  30};
  31
  32/**
  33 * struct inet_frag_queue - fragment queue
  34 *
  35 * @lock: spinlock protecting the queue
  36 * @timer: queue expiration timer
  37 * @list: hash bucket list
  38 * @refcnt: reference count of the queue
  39 * @fragments: received fragments head
  40 * @fragments_tail: received fragments tail
  41 * @stamp: timestamp of the last received fragment
  42 * @len: total length of the original datagram
  43 * @meat: length of received fragments so far
  44 * @flags: fragment queue flags
  45 * @max_size: maximum received fragment size
  46 * @net: namespace that this frag belongs to
  47 * @list_evictor: list of queues to forcefully evict (e.g. due to low memory)
  48 */
  49struct inet_frag_queue {
  50        spinlock_t              lock;
  51        struct timer_list       timer;
  52        struct hlist_node       list;
  53        atomic_t                refcnt;
  54        struct sk_buff          *fragments;
  55        struct sk_buff          *fragments_tail;
  56        ktime_t                 stamp;
  57        int                     len;
  58        int                     meat;
  59        __u8                    flags;
  60        u16                     max_size;
  61        struct netns_frags      *net;
  62        struct hlist_node       list_evictor;
  63};
  64
  65#define INETFRAGS_HASHSZ        1024
  66
  67/* averaged:
  68 * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
  69 *             rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
  70 *             struct frag_queue))
  71 */
  72#define INETFRAGS_MAXDEPTH      128
  73
  74struct inet_frag_bucket {
  75        struct hlist_head       chain;
  76        spinlock_t              chain_lock;
  77};
  78
  79struct inet_frags {
  80        struct inet_frag_bucket hash[INETFRAGS_HASHSZ];
  81
  82        struct work_struct      frags_work;
  83        unsigned int next_bucket;
  84        unsigned long last_rebuild_jiffies;
  85        bool rebuild;
  86
  87        /* The first call to hashfn is responsible to initialize
  88         * rnd. This is best done with net_get_random_once.
  89         *
  90         * rnd_seqlock is used to let hash insertion detect
  91         * when it needs to re-lookup the hash chain to use.
  92         */
  93        u32                     rnd;
  94        seqlock_t               rnd_seqlock;
  95        int                     qsize;
  96
  97        unsigned int            (*hashfn)(const struct inet_frag_queue *);
  98        bool                    (*match)(const struct inet_frag_queue *q,
  99                                         const void *arg);
 100        void                    (*constructor)(struct inet_frag_queue *q,
 101                                               const void *arg);
 102        void                    (*destructor)(struct inet_frag_queue *);
 103        void                    (*frag_expire)(unsigned long data);
 104        struct kmem_cache       *frags_cachep;
 105        const char              *frags_cache_name;
 106};
 107
 108int inet_frags_init(struct inet_frags *);
 109void inet_frags_fini(struct inet_frags *);
 110
 111static inline int inet_frags_init_net(struct netns_frags *nf)
 112{
 113        return percpu_counter_init(&nf->mem, 0, GFP_KERNEL);
 114}
 115static inline void inet_frags_uninit_net(struct netns_frags *nf)
 116{
 117        percpu_counter_destroy(&nf->mem);
 118}
 119
 120void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f);
 121
 122void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f);
 123void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f);
 124struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
 125                struct inet_frags *f, void *key, unsigned int hash);
 126
 127void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
 128                                   const char *prefix);
 129
 130static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
 131{
 132        if (atomic_dec_and_test(&q->refcnt))
 133                inet_frag_destroy(q, f);
 134}
 135
 136static inline bool inet_frag_evicting(struct inet_frag_queue *q)
 137{
 138        return !hlist_unhashed(&q->list_evictor);
 139}
 140
 141/* Memory Tracking Functions. */
 142
 143/* The default percpu_counter batch size is not big enough to scale to
 144 * fragmentation mem acct sizes.
 145 * The mem size of a 64K fragment is approx:
 146 *  (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes
 147 */
 148static unsigned int frag_percpu_counter_batch = 130000;
 149
 150static inline int frag_mem_limit(struct netns_frags *nf)
 151{
 152        return percpu_counter_read(&nf->mem);
 153}
 154
 155static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
 156{
 157        __percpu_counter_add(&nf->mem, -i, frag_percpu_counter_batch);
 158}
 159
 160static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
 161{
 162        __percpu_counter_add(&nf->mem, i, frag_percpu_counter_batch);
 163}
 164
 165static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf)
 166{
 167        unsigned int res;
 168
 169        local_bh_disable();
 170        res = percpu_counter_sum_positive(&nf->mem);
 171        local_bh_enable();
 172
 173        return res;
 174}
 175
 176/* RFC 3168 support :
 177 * We want to check ECN values of all fragments, do detect invalid combinations.
 178 * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
 179 */
 180#define IPFRAG_ECN_NOT_ECT      0x01 /* one frag had ECN_NOT_ECT */
 181#define IPFRAG_ECN_ECT_1        0x02 /* one frag had ECN_ECT_1 */
 182#define IPFRAG_ECN_ECT_0        0x04 /* one frag had ECN_ECT_0 */
 183#define IPFRAG_ECN_CE           0x08 /* one frag had ECN_CE */
 184
 185extern const u8 ip_frag_ecn_table[16];
 186
 187#endif
 188