1 #ifndef __NET_FRAG_H__ 2 #define __NET_FRAG_H__ 3 4 #include <linux/percpu_counter.h> 5 6 struct netns_frags { 7 int nqueues; 8 struct list_head lru_list; 9 spinlock_t lru_lock; 10 11 /* The percpu_counter "mem" need to be cacheline aligned. 12 * mem.count must not share cacheline with other writers 13 */ 14 struct percpu_counter mem ____cacheline_aligned_in_smp; 15 16 /* sysctls */ 17 int timeout; 18 int high_thresh; 19 int low_thresh; 20 }; 21 22 struct inet_frag_queue { 23 spinlock_t lock; 24 struct timer_list timer; /* when will this queue expire? */ 25 struct list_head lru_list; /* lru list member */ 26 struct hlist_node list; 27 atomic_t refcnt; 28 struct sk_buff *fragments; /* list of received fragments */ 29 struct sk_buff *fragments_tail; 30 ktime_t stamp; 31 int len; /* total length of orig datagram */ 32 int meat; 33 __u8 last_in; /* first/last segment arrived? */ 34 35 #define INET_FRAG_COMPLETE 4 36 #define INET_FRAG_FIRST_IN 2 37 #define INET_FRAG_LAST_IN 1 38 39 u16 max_size; 40 41 struct netns_frags *net; 42 }; 43 44 #define INETFRAGS_HASHSZ 1024 45 46 /* averaged: 47 * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ / 48 * rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or 49 * struct frag_queue)) 50 */ 51 #define INETFRAGS_MAXDEPTH 128 52 53 struct inet_frag_bucket { 54 struct hlist_head chain; 55 spinlock_t chain_lock; 56 }; 57 58 struct inet_frags { 59 struct inet_frag_bucket hash[INETFRAGS_HASHSZ]; 60 /* This rwlock is a global lock (seperate per IPv4, IPv6 and 61 * netfilter). Important to keep this on a seperate cacheline. 62 * Its primarily a rebuild protection rwlock. 63 */ 64 rwlock_t lock ____cacheline_aligned_in_smp; 65 int secret_interval; 66 struct timer_list secret_timer; 67 u32 rnd; 68 int qsize; 69 70 unsigned int (*hashfn)(struct inet_frag_queue *); 71 bool (*match)(struct inet_frag_queue *q, void *arg); 72 void (*constructor)(struct inet_frag_queue *q, 73 void *arg); 74 void (*destructor)(struct inet_frag_queue *); 75 void (*skb_free)(struct sk_buff *); 76 void (*frag_expire)(unsigned long data); 77 }; 78 79 void inet_frags_init(struct inet_frags *); 80 void inet_frags_fini(struct inet_frags *); 81 82 void inet_frags_init_net(struct netns_frags *nf); 83 void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f); 84 85 void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); 86 void inet_frag_destroy(struct inet_frag_queue *q, 87 struct inet_frags *f, int *work); 88 int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force); 89 struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, 90 struct inet_frags *f, void *key, unsigned int hash) 91 __releases(&f->lock); 92 void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q, 93 const char *prefix); 94 95 static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) 96 { 97 if (atomic_dec_and_test(&q->refcnt)) 98 inet_frag_destroy(q, f, NULL); 99 } 100 101 /* Memory Tracking Functions. */ 102 103 /* The default percpu_counter batch size is not big enough to scale to 104 * fragmentation mem acct sizes. 105 * The mem size of a 64K fragment is approx: 106 * (44 fragments * 2944 truesize) + frag_queue struct(200) = 129736 bytes 107 */ 108 static unsigned int frag_percpu_counter_batch = 130000; 109 110 static inline int frag_mem_limit(struct netns_frags *nf) 111 { 112 return percpu_counter_read(&nf->mem); 113 } 114 115 static inline void sub_frag_mem_limit(struct inet_frag_queue *q, int i) 116 { 117 __percpu_counter_add(&q->net->mem, -i, frag_percpu_counter_batch); 118 } 119 120 static inline void add_frag_mem_limit(struct inet_frag_queue *q, int i) 121 { 122 __percpu_counter_add(&q->net->mem, i, frag_percpu_counter_batch); 123 } 124 125 static inline void init_frag_mem_limit(struct netns_frags *nf) 126 { 127 percpu_counter_init(&nf->mem, 0); 128 } 129 130 static inline int sum_frag_mem_limit(struct netns_frags *nf) 131 { 132 int res; 133 134 local_bh_disable(); 135 res = percpu_counter_sum_positive(&nf->mem); 136 local_bh_enable(); 137 138 return res; 139 } 140 141 static inline void inet_frag_lru_move(struct inet_frag_queue *q) 142 { 143 spin_lock(&q->net->lru_lock); 144 if (!list_empty(&q->lru_list)) 145 list_move_tail(&q->lru_list, &q->net->lru_list); 146 spin_unlock(&q->net->lru_lock); 147 } 148 149 static inline void inet_frag_lru_del(struct inet_frag_queue *q) 150 { 151 spin_lock(&q->net->lru_lock); 152 list_del_init(&q->lru_list); 153 q->net->nqueues--; 154 spin_unlock(&q->net->lru_lock); 155 } 156 157 static inline void inet_frag_lru_add(struct netns_frags *nf, 158 struct inet_frag_queue *q) 159 { 160 spin_lock(&nf->lru_lock); 161 list_add_tail(&q->lru_list, &nf->lru_list); 162 q->net->nqueues++; 163 spin_unlock(&nf->lru_lock); 164 } 165 166 /* RFC 3168 support : 167 * We want to check ECN values of all fragments, do detect invalid combinations. 168 * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value. 169 */ 170 #define IPFRAG_ECN_NOT_ECT 0x01 /* one frag had ECN_NOT_ECT */ 171 #define IPFRAG_ECN_ECT_1 0x02 /* one frag had ECN_ECT_1 */ 172 #define IPFRAG_ECN_ECT_0 0x04 /* one frag had ECN_ECT_0 */ 173 #define IPFRAG_ECN_CE 0x08 /* one frag had ECN_CE */ 174 175 extern const u8 ip_frag_ecn_table[16]; 176 177 #endif 178