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