RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / include / linux / netfilter_ipv4 / ip_set_hashes.h
blob8eeced31403df2b0b0909a66d2136115ec455a45
1 #ifndef __IP_SET_HASHES_H
2 #define __IP_SET_HASHES_H
4 #define initval_t uint32_t
6 /* Macros to generate functions */
8 #ifdef __KERNEL__
9 #define HASH_RETRY0(type, dtype, cond) \
10 static int \
11 type##_retry(struct ip_set *set) \
12 { \
13 struct ip_set_##type *map = set->data, *tmp; \
14 dtype *elem; \
15 void *members; \
16 u_int32_t i, hashsize = map->hashsize; \
17 int res; \
19 if (map->resize == 0) \
20 return -ERANGE; \
22 again: \
23 res = 0; \
25 /* Calculate new hash size */ \
26 hashsize += (hashsize * map->resize)/100; \
27 if (hashsize == map->hashsize) \
28 hashsize++; \
30 ip_set_printk("rehashing of set %s triggered: " \
31 "hashsize grows from %lu to %lu", \
32 set->name, \
33 (long unsigned)map->hashsize, \
34 (long unsigned)hashsize); \
36 tmp = kmalloc(sizeof(struct ip_set_##type) \
37 + map->probes * sizeof(initval_t), GFP_ATOMIC); \
38 if (!tmp) { \
39 DP("out of memory for %zu bytes", \
40 sizeof(struct ip_set_##type) \
41 + map->probes * sizeof(initval_t)); \
42 return -ENOMEM; \
43 } \
44 tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\
45 if (!tmp->members) { \
46 DP("out of memory for %zu bytes", hashsize * sizeof(dtype));\
47 kfree(tmp); \
48 return -ENOMEM; \
49 } \
50 tmp->hashsize = hashsize; \
51 tmp->elements = 0; \
52 tmp->probes = map->probes; \
53 tmp->resize = map->resize; \
54 memcpy(tmp->initval, map->initval, map->probes * sizeof(initval_t));\
55 __##type##_retry(tmp, map); \
57 write_lock_bh(&set->lock); \
58 map = set->data; /* Play safe */ \
59 for (i = 0; i < map->hashsize && res == 0; i++) { \
60 elem = HARRAY_ELEM(map->members, dtype *, i); \
61 if (cond) \
62 res = __##type##_add(tmp, elem); \
63 } \
64 if (res) { \
65 /* Failure, try again */ \
66 write_unlock_bh(&set->lock); \
67 harray_free(tmp->members); \
68 kfree(tmp); \
69 goto again; \
70 } \
72 /* Success at resizing! */ \
73 members = map->members; \
75 map->hashsize = tmp->hashsize; \
76 map->members = tmp->members; \
77 write_unlock_bh(&set->lock); \
79 harray_free(members); \
80 kfree(tmp); \
82 return 0; \
85 #define HASH_RETRY(type, dtype) \
86 HASH_RETRY0(type, dtype, *elem)
88 #define HASH_RETRY2(type, dtype) \
89 HASH_RETRY0(type, dtype, elem->ip || elem->ip1)
91 #define HASH_CREATE(type, dtype) \
92 static int \
93 type##_create(struct ip_set *set, const void *data, u_int32_t size) \
94 { \
95 const struct ip_set_req_##type##_create *req = data; \
96 struct ip_set_##type *map; \
97 uint16_t i; \
99 if (req->hashsize < 1) { \
100 ip_set_printk("hashsize too small"); \
101 return -ENOEXEC; \
104 if (req->probes < 1) { \
105 ip_set_printk("probes too small"); \
106 return -ENOEXEC; \
109 map = kmalloc(sizeof(struct ip_set_##type) \
110 + req->probes * sizeof(initval_t), GFP_KERNEL); \
111 if (!map) { \
112 DP("out of memory for %zu bytes", \
113 sizeof(struct ip_set_##type) \
114 + req->probes * sizeof(initval_t)); \
115 return -ENOMEM; \
117 for (i = 0; i < req->probes; i++) \
118 get_random_bytes(((initval_t *) map->initval)+i, 4); \
119 map->elements = 0; \
120 map->hashsize = req->hashsize; \
121 map->probes = req->probes; \
122 map->resize = req->resize; \
123 if (__##type##_create(req, map)) { \
124 kfree(map); \
125 return -ENOEXEC; \
127 map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\
128 if (!map->members) { \
129 DP("out of memory for %zu bytes", map->hashsize * sizeof(dtype));\
130 kfree(map); \
131 return -ENOMEM; \
134 set->data = map; \
135 return 0; \
138 #define HASH_DESTROY(type) \
139 static void \
140 type##_destroy(struct ip_set *set) \
142 struct ip_set_##type *map = set->data; \
144 harray_free(map->members); \
145 kfree(map); \
147 set->data = NULL; \
150 #define HASH_FLUSH(type, dtype) \
151 static void \
152 type##_flush(struct ip_set *set) \
154 struct ip_set_##type *map = set->data; \
155 harray_flush(map->members, map->hashsize, sizeof(dtype)); \
156 map->elements = 0; \
159 #define HASH_FLUSH_CIDR(type, dtype) \
160 static void \
161 type##_flush(struct ip_set *set) \
163 struct ip_set_##type *map = set->data; \
164 harray_flush(map->members, map->hashsize, sizeof(dtype)); \
165 memset(map->cidr, 0, sizeof(map->cidr)); \
166 memset(map->nets, 0, sizeof(map->nets)); \
167 map->elements = 0; \
170 #define HASH_LIST_HEADER(type) \
171 static void \
172 type##_list_header(const struct ip_set *set, void *data) \
174 const struct ip_set_##type *map = set->data; \
175 struct ip_set_req_##type##_create *header = data; \
177 header->hashsize = map->hashsize; \
178 header->probes = map->probes; \
179 header->resize = map->resize; \
180 __##type##_list_header(map, header); \
183 #define HASH_LIST_MEMBERS_SIZE(type, dtype) \
184 static int \
185 type##_list_members_size(const struct ip_set *set, char dont_align) \
187 const struct ip_set_##type *map = set->data; \
189 return (map->elements * IPSET_VALIGN(sizeof(dtype), dont_align));\
192 #define HASH_LIST_MEMBERS(type, dtype) \
193 static void \
194 type##_list_members(const struct ip_set *set, void *data, char dont_align)\
196 const struct ip_set_##type *map = set->data; \
197 dtype *elem, *d; \
198 uint32_t i, n = 0; \
200 for (i = 0; i < map->hashsize; i++) { \
201 elem = HARRAY_ELEM(map->members, dtype *, i); \
202 if (*elem) { \
203 d = data + n * IPSET_VALIGN(sizeof(dtype), dont_align);\
204 *d = *elem; \
205 n++; \
210 #define HASH_LIST_MEMBERS_MEMCPY(type, dtype, nonzero) \
211 static void \
212 type##_list_members(const struct ip_set *set, void *data, char dont_align)\
214 const struct ip_set_##type *map = set->data; \
215 dtype *elem; \
216 uint32_t i, n = 0; \
218 for (i = 0; i < map->hashsize; i++) { \
219 elem = HARRAY_ELEM(map->members, dtype *, i); \
220 if (nonzero) { \
221 memcpy(data + n * IPSET_VALIGN(sizeof(dtype), dont_align),\
222 elem, sizeof(dtype)); \
223 n++; \
228 #define IP_SET_RTYPE(type, __features) \
229 struct ip_set_type ip_set_##type = { \
230 .typename = #type, \
231 .features = __features, \
232 .protocol_version = IP_SET_PROTOCOL_VERSION, \
233 .create = &type##_create, \
234 .retry = &type##_retry, \
235 .destroy = &type##_destroy, \
236 .flush = &type##_flush, \
237 .reqsize = sizeof(struct ip_set_req_##type), \
238 .addip = &type##_uadd, \
239 .addip_kernel = &type##_kadd, \
240 .delip = &type##_udel, \
241 .delip_kernel = &type##_kdel, \
242 .testip = &type##_utest, \
243 .testip_kernel = &type##_ktest, \
244 .header_size = sizeof(struct ip_set_req_##type##_create),\
245 .list_header = &type##_list_header, \
246 .list_members_size = &type##_list_members_size, \
247 .list_members = &type##_list_members, \
248 .me = THIS_MODULE, \
251 /* Helper functions */
252 static inline void
253 add_cidr_size(uint8_t *cidr, uint8_t size)
255 uint8_t next;
256 int i;
258 for (i = 0; i < 30 && cidr[i]; i++) {
259 if (cidr[i] < size) {
260 next = cidr[i];
261 cidr[i] = size;
262 size = next;
265 if (i < 30)
266 cidr[i] = size;
269 static inline void
270 del_cidr_size(uint8_t *cidr, uint8_t size)
272 int i;
274 for (i = 0; i < 29 && cidr[i]; i++) {
275 if (cidr[i] == size)
276 cidr[i] = size = cidr[i+1];
278 cidr[29] = 0;
280 #else
281 #include <arpa/inet.h>
282 #endif /* __KERNEL */
284 #ifndef UINT16_MAX
285 #define UINT16_MAX 65535
286 #endif
288 static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
290 static inline ip_set_ip_t
291 pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr)
293 ip_set_ip_t addr, *paddr = &addr;
294 unsigned char n, t, *a;
296 addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
297 #ifdef __KERNEL__
298 DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
299 #endif
300 n = cidr / 8;
301 t = cidr % 8;
302 a = &((unsigned char *)paddr)[n];
303 *a = *a /(1 << (8 - t)) + shifts[t];
304 #ifdef __KERNEL__
305 DP("n: %u, t: %u, a: %u", n, t, *a);
306 DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
307 HIPQUAD(ip), cidr, NIPQUAD(addr));
308 #endif
310 return ntohl(addr);
314 #endif /* __IP_SET_HASHES_H */