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 */