1 #ifndef __IP_SET_HASHES_H
2 #define __IP_SET_HASHES_H
4 #define initval_t uint32_t
6 /* Macros to generate functions */
9 #define HASH_RETRY0(type, dtype, cond) \
11 type##_retry(struct ip_set *set) \
13 struct ip_set_##type *map = set->data, *tmp; \
16 u_int32_t i, hashsize = map->hashsize; \
19 if (map->resize == 0) \
25 /* Calculate new hash size */ \
26 hashsize += (hashsize * map->resize)/100; \
27 if (hashsize == map->hashsize) \
30 ip_set_printk("rehashing of set %s triggered: " \
31 "hashsize grows from %lu to %lu", \
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); \
39 DP("out of memory for %zu bytes", \
40 sizeof(struct ip_set_##type) \
41 + map->probes * sizeof(initval_t)); \
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));\
50 tmp->hashsize = hashsize; \
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); \
62 res = __##type##_add(tmp, elem); \
65 /* Failure, try again */ \
66 write_unlock_bh(&set->lock); \
67 harray_free(tmp->members); \
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); \
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) \
93 type##_create(struct ip_set *set, const void *data, u_int32_t size) \
95 const struct ip_set_req_##type##_create *req = data; \
96 struct ip_set_##type *map; \
99 if (req->hashsize < 1) { \
100 ip_set_printk("hashsize too small"); \
104 if (req->probes < 1) { \
105 ip_set_printk("probes too small"); \
109 map = kmalloc(sizeof(struct ip_set_##type) \
110 + req->probes * sizeof(initval_t), GFP_KERNEL); \
112 DP("out of memory for %zu bytes", \
113 sizeof(struct ip_set_##type) \
114 + req->probes * sizeof(initval_t)); \
117 for (i = 0; i < req->probes; i++) \
118 get_random_bytes(((initval_t *) map->initval)+i, 4); \
120 map->hashsize = req->hashsize; \
121 map->probes = req->probes; \
122 map->resize = req->resize; \
123 if (__##type##_create(req, map)) { \
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));\
138 #define HASH_DESTROY(type) \
140 type##_destroy(struct ip_set *set) \
142 struct ip_set_##type *map = set->data; \
144 harray_free(map->members); \
150 #define HASH_FLUSH(type, dtype) \
152 type##_flush(struct ip_set *set) \
154 struct ip_set_##type *map = set->data; \
155 harray_flush(map->members, map->hashsize, sizeof(dtype)); \
159 #define HASH_FLUSH_CIDR(type, dtype) \
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)); \
170 #define HASH_LIST_HEADER(type) \
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) \
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) \
194 type##_list_members(const struct ip_set *set, void *data, char dont_align)\
196 const struct ip_set_##type *map = set->data; \
200 for (i = 0; i < map->hashsize; i++) { \
201 elem = HARRAY_ELEM(map->members, dtype *, i); \
203 d = data + n * IPSET_VALIGN(sizeof(dtype), dont_align);\
210 #define HASH_LIST_MEMBERS_MEMCPY(type, dtype, nonzero) \
212 type##_list_members(const struct ip_set *set, void *data, char dont_align)\
214 const struct ip_set_##type *map = set->data; \
218 for (i = 0; i < map->hashsize; i++) { \
219 elem = HARRAY_ELEM(map->members, dtype *, i); \
221 memcpy(data + n * IPSET_VALIGN(sizeof(dtype), dont_align),\
222 elem, sizeof(dtype)); \
228 #define IP_SET_RTYPE(type, __features) \
229 struct ip_set_type ip_set_##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, \
251 /* Helper functions */
253 add_cidr_size(uint8_t *cidr
, uint8_t size
)
258 for (i
= 0; i
< 30 && cidr
[i
]; i
++) {
259 if (cidr
[i
] < size
) {
270 del_cidr_size(uint8_t *cidr
, uint8_t size
)
274 for (i
= 0; i
< 29 && cidr
[i
]; i
++) {
276 cidr
[i
] = size
= cidr
[i
+1];
281 #include <arpa/inet.h>
282 #endif /* __KERNEL */
285 #define UINT16_MAX 65535
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
))));
298 DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr
), cidr
);
302 a
= &((unsigned char *)paddr
)[n
];
303 *a
= *a
/(1 << (8 - t
)) + shifts
[t
];
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
));
314 #endif /* __IP_SET_HASHES_H */