Merge branch 'ipset'

Conflicts:
	doc/changelog.txt
This commit is contained in:
Jan Engelhardt
2011-08-12 15:37:50 +02:00
10 changed files with 138 additions and 61 deletions

View File

@@ -5,6 +5,7 @@ HEAD
- xt_TEE: abort build when the feature is already provided by mainline - xt_TEE: abort build when the feature is already provided by mainline
- xt_psd: restore functionality with UDP - xt_psd: restore functionality with UDP
- xt_psd: support UDPLITE - xt_psd: support UDPLITE
- update to ipset 6.8
v1.37 (2011-06-25) v1.37 (2011-06-25)

View File

@@ -28,7 +28,32 @@
/* Number of elements to store in an initial array block */ /* Number of elements to store in an initial array block */
#define AHASH_INIT_SIZE 4 #define AHASH_INIT_SIZE 4
/* Max number of elements to store in an array block */ /* Max number of elements to store in an array block */
#define AHASH_MAX_SIZE (3*4) #define AHASH_MAX_SIZE (3*AHASH_INIT_SIZE)
/* Max number of elements can be tuned */
#ifdef IP_SET_HASH_WITH_MULTI
#define AHASH_MAX(h) ((h)->ahash_max)
static inline u8
tune_ahash_max(u8 curr, u32 multi)
{
u32 n;
if (multi < curr)
return curr;
n = curr + AHASH_INIT_SIZE;
/* Currently, at listing one hash bucket must fit into a message.
* Therefore we have a hard limit here.
*/
return n > curr && n <= 64 ? n : curr;
}
#define TUNE_AHASH_MAX(h, multi) \
((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi))
#else
#define AHASH_MAX(h) AHASH_MAX_SIZE
#define TUNE_AHASH_MAX(h, multi)
#endif
/* A hash bucket */ /* A hash bucket */
struct hbucket { struct hbucket {
@@ -60,6 +85,9 @@ struct ip_set_hash {
u32 timeout; /* timeout value, if enabled */ u32 timeout; /* timeout value, if enabled */
struct timer_list gc; /* garbage collection when timeout enabled */ struct timer_list gc; /* garbage collection when timeout enabled */
struct type_pf_next next; /* temporary storage for uadd */ struct type_pf_next next; /* temporary storage for uadd */
#ifdef IP_SET_HASH_WITH_MULTI
u8 ahash_max; /* max elements in an array block */
#endif
#ifdef IP_SET_HASH_WITH_NETMASK #ifdef IP_SET_HASH_WITH_NETMASK
u8 netmask; /* netmask value for subnets to store */ u8 netmask; /* netmask value for subnets to store */
#endif #endif
@@ -211,12 +239,16 @@ ip_set_hash_destroy(struct ip_set *set)
set->data = NULL; set->data = NULL;
} }
#define HKEY(data, initval, htable_bits) \
(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \
& jhash_mask(htable_bits))
#endif /* _IP_SET_AHASH_H */ #endif /* _IP_SET_AHASH_H */
#ifndef HKEY_DATALEN
#define HKEY_DATALEN sizeof(struct type_pf_elem)
#endif
#define HKEY(data, initval, htable_bits) \
(jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \
& jhash_mask(htable_bits))
#define CONCAT(a, b, c) a##b##c #define CONCAT(a, b, c) a##b##c
#define TOKEN(a, b, c) CONCAT(a, b, c) #define TOKEN(a, b, c) CONCAT(a, b, c)
@@ -275,12 +307,13 @@ ip_set_hash_destroy(struct ip_set *set)
/* Add an element to the hash table when resizing the set: /* Add an element to the hash table when resizing the set:
* we spare the maintenance of the internal counters. */ * we spare the maintenance of the internal counters. */
static int static int
type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value) type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value,
u8 ahash_max)
{ {
if (n->pos >= n->size) { if (n->pos >= n->size) {
void *tmp; void *tmp;
if (n->size >= AHASH_MAX_SIZE) if (n->size >= ahash_max)
/* Trigger rehashing */ /* Trigger rehashing */
return -EAGAIN; return -EAGAIN;
@@ -335,7 +368,7 @@ retry:
for (j = 0; j < n->pos; j++) { for (j = 0; j < n->pos; j++) {
data = ahash_data(n, j); data = ahash_data(n, j);
m = hbucket(t, HKEY(data, h->initval, htable_bits)); m = hbucket(t, HKEY(data, h->initval, htable_bits));
ret = type_pf_elem_add(m, data); ret = type_pf_elem_add(m, data, AHASH_MAX(h));
if (ret < 0) { if (ret < 0) {
read_unlock_bh(&set->lock); read_unlock_bh(&set->lock);
ahash_destroy(t); ahash_destroy(t);
@@ -359,7 +392,7 @@ retry:
return 0; return 0;
} }
static void static inline void
type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d); type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
/* Add an element to a hash and update the internal counters when succeeded, /* Add an element to a hash and update the internal counters when succeeded,
@@ -372,7 +405,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
const struct type_pf_elem *d = value; const struct type_pf_elem *d = value;
struct hbucket *n; struct hbucket *n;
int i, ret = 0; int i, ret = 0;
u32 key; u32 key, multi = 0;
if (h->elements >= h->maxelem) if (h->elements >= h->maxelem)
return -IPSET_ERR_HASH_FULL; return -IPSET_ERR_HASH_FULL;
@@ -382,12 +415,12 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
key = HKEY(value, h->initval, t->htable_bits); key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) for (i = 0; i < n->pos; i++)
if (type_pf_data_equal(ahash_data(n, i), d)) { if (type_pf_data_equal(ahash_data(n, i), d, &multi)) {
ret = -IPSET_ERR_EXIST; ret = -IPSET_ERR_EXIST;
goto out; goto out;
} }
TUNE_AHASH_MAX(h, multi);
ret = type_pf_elem_add(n, value); ret = type_pf_elem_add(n, value, AHASH_MAX(h));
if (ret != 0) { if (ret != 0) {
if (ret == -EAGAIN) if (ret == -EAGAIN)
type_pf_data_next(h, d); type_pf_data_next(h, d);
@@ -415,13 +448,13 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct hbucket *n; struct hbucket *n;
int i; int i;
struct type_pf_elem *data; struct type_pf_elem *data;
u32 key; u32 key, multi = 0;
key = HKEY(value, h->initval, t->htable_bits); key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i); data = ahash_data(n, i);
if (!type_pf_data_equal(data, d)) if (!type_pf_data_equal(data, d, &multi))
continue; continue;
if (i != n->pos - 1) if (i != n->pos - 1)
/* Not last one */ /* Not last one */
@@ -462,17 +495,17 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
struct hbucket *n; struct hbucket *n;
const struct type_pf_elem *data; const struct type_pf_elem *data;
int i, j = 0; int i, j = 0;
u32 key; u32 key, multi = 0;
u8 host_mask = SET_HOST_MASK(set->family); u8 host_mask = SET_HOST_MASK(set->family);
pr_debug("test by nets\n"); pr_debug("test by nets\n");
for (; j < host_mask && h->nets[j].cidr; j++) { for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
type_pf_data_netmask(d, h->nets[j].cidr); type_pf_data_netmask(d, h->nets[j].cidr);
key = HKEY(d, h->initval, t->htable_bits); key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i); data = ahash_data(n, i);
if (type_pf_data_equal(data, d)) if (type_pf_data_equal(data, d, &multi))
return 1; return 1;
} }
} }
@@ -490,7 +523,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct hbucket *n; struct hbucket *n;
const struct type_pf_elem *data; const struct type_pf_elem *data;
int i; int i;
u32 key; u32 key, multi = 0;
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
/* If we test an IP address and not a network address, /* If we test an IP address and not a network address,
@@ -503,7 +536,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i); data = ahash_data(n, i);
if (type_pf_data_equal(data, d)) if (type_pf_data_equal(data, d, &multi))
return 1; return 1;
} }
return 0; return 0;
@@ -660,14 +693,14 @@ type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
static int static int
type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
u32 timeout) u8 ahash_max, u32 timeout)
{ {
struct type_pf_elem *data; struct type_pf_elem *data;
if (n->pos >= n->size) { if (n->pos >= n->size) {
void *tmp; void *tmp;
if (n->size >= AHASH_MAX_SIZE) if (n->size >= ahash_max)
/* Trigger rehashing */ /* Trigger rehashing */
return -EAGAIN; return -EAGAIN;
@@ -772,7 +805,7 @@ retry:
for (j = 0; j < n->pos; j++) { for (j = 0; j < n->pos; j++) {
data = ahash_tdata(n, j); data = ahash_tdata(n, j);
m = hbucket(t, HKEY(data, h->initval, htable_bits)); m = hbucket(t, HKEY(data, h->initval, htable_bits));
ret = type_pf_elem_tadd(m, data, ret = type_pf_elem_tadd(m, data, AHASH_MAX(h),
type_pf_data_timeout(data)); type_pf_data_timeout(data));
if (ret < 0) { if (ret < 0) {
read_unlock_bh(&set->lock); read_unlock_bh(&set->lock);
@@ -803,9 +836,9 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
const struct type_pf_elem *d = value; const struct type_pf_elem *d = value;
struct hbucket *n; struct hbucket *n;
struct type_pf_elem *data; struct type_pf_elem *data;
int ret = 0, i, j = AHASH_MAX_SIZE + 1; int ret = 0, i, j = AHASH_MAX(h) + 1;
bool flag_exist = flags & IPSET_FLAG_EXIST; bool flag_exist = flags & IPSET_FLAG_EXIST;
u32 key; u32 key, multi = 0;
if (h->elements >= h->maxelem) if (h->elements >= h->maxelem)
/* FIXME: when set is full, we slow down here */ /* FIXME: when set is full, we slow down here */
@@ -819,18 +852,18 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i); data = ahash_tdata(n, i);
if (type_pf_data_equal(data, d)) { if (type_pf_data_equal(data, d, &multi)) {
if (type_pf_data_expired(data) || flag_exist) if (type_pf_data_expired(data) || flag_exist)
j = i; j = i;
else { else {
ret = -IPSET_ERR_EXIST; ret = -IPSET_ERR_EXIST;
goto out; goto out;
} }
} else if (j == AHASH_MAX_SIZE + 1 && } else if (j == AHASH_MAX(h) + 1 &&
type_pf_data_expired(data)) type_pf_data_expired(data))
j = i; j = i;
} }
if (j != AHASH_MAX_SIZE + 1) { if (j != AHASH_MAX(h) + 1) {
data = ahash_tdata(n, j); data = ahash_tdata(n, j);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
del_cidr(h, data->cidr, HOST_MASK); del_cidr(h, data->cidr, HOST_MASK);
@@ -840,7 +873,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
type_pf_data_timeout_set(data, timeout); type_pf_data_timeout_set(data, timeout);
goto out; goto out;
} }
ret = type_pf_elem_tadd(n, d, timeout); TUNE_AHASH_MAX(h, multi);
ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout);
if (ret != 0) { if (ret != 0) {
if (ret == -EAGAIN) if (ret == -EAGAIN)
type_pf_data_next(h, d); type_pf_data_next(h, d);
@@ -865,13 +899,13 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct hbucket *n; struct hbucket *n;
int i; int i;
struct type_pf_elem *data; struct type_pf_elem *data;
u32 key; u32 key, multi = 0;
key = HKEY(value, h->initval, t->htable_bits); key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i); data = ahash_tdata(n, i);
if (!type_pf_data_equal(data, d)) if (!type_pf_data_equal(data, d, &multi))
continue; continue;
if (type_pf_data_expired(data)) if (type_pf_data_expired(data))
return -IPSET_ERR_EXIST; return -IPSET_ERR_EXIST;
@@ -911,16 +945,16 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
struct type_pf_elem *data; struct type_pf_elem *data;
struct hbucket *n; struct hbucket *n;
int i, j = 0; int i, j = 0;
u32 key; u32 key, multi = 0;
u8 host_mask = SET_HOST_MASK(set->family); u8 host_mask = SET_HOST_MASK(set->family);
for (; j < host_mask && h->nets[j].cidr; j++) { for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
type_pf_data_netmask(d, h->nets[j].cidr); type_pf_data_netmask(d, h->nets[j].cidr);
key = HKEY(d, h->initval, t->htable_bits); key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i); data = ahash_tdata(n, i);
if (type_pf_data_equal(data, d)) if (type_pf_data_equal(data, d, &multi))
return !type_pf_data_expired(data); return !type_pf_data_expired(data);
} }
} }
@@ -936,7 +970,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct type_pf_elem *data, *d = value; struct type_pf_elem *data, *d = value;
struct hbucket *n; struct hbucket *n;
int i; int i;
u32 key; u32 key, multi = 0;
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
if (d->cidr == SET_HOST_MASK(set->family)) if (d->cidr == SET_HOST_MASK(set->family))
@@ -946,7 +980,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i); data = ahash_tdata(n, i);
if (type_pf_data_equal(data, d)) if (type_pf_data_equal(data, d, &multi))
return !type_pf_data_expired(data); return !type_pf_data_expired(data);
} }
return 0; return 0;
@@ -1054,6 +1088,8 @@ type_pf_gc_init(struct ip_set *set)
IPSET_GC_PERIOD(h->timeout)); IPSET_GC_PERIOD(h->timeout));
} }
#undef HKEY_DATALEN
#undef HKEY
#undef type_pf_data_equal #undef type_pf_data_equal
#undef type_pf_data_isnull #undef type_pf_data_isnull
#undef type_pf_data_copy #undef type_pf_data_copy

View File

@@ -53,7 +53,8 @@ struct hash_ip4_telem {
static inline bool static inline bool
hash_ip4_data_equal(const struct hash_ip4_elem *ip1, hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
const struct hash_ip4_elem *ip2) const struct hash_ip4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip; return ip1->ip == ip2->ip;
} }
@@ -225,7 +226,8 @@ struct hash_ip6_telem {
static inline bool static inline bool
hash_ip6_data_equal(const struct hash_ip6_elem *ip1, hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
const struct hash_ip6_elem *ip2) const struct hash_ip6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0; return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
} }

View File

@@ -60,7 +60,8 @@ struct hash_ipport4_telem {
static inline bool static inline bool
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
const struct hash_ipport4_elem *ip2) const struct hash_ipport4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip && return ip1->ip == ip2->ip &&
ip1->port == ip2->port && ip1->port == ip2->port &&
@@ -276,7 +277,8 @@ struct hash_ipport6_telem {
static inline bool static inline bool
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
const struct hash_ipport6_elem *ip2) const struct hash_ipport6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port && ip1->port == ip2->port &&

View File

@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
static inline bool static inline bool
hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
const struct hash_ipportip4_elem *ip2) const struct hash_ipportip4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip && return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 && ip1->ip2 == ip2->ip2 &&
@@ -286,7 +287,8 @@ struct hash_ipportip6_telem {
static inline bool static inline bool
hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
const struct hash_ipportip6_elem *ip2) const struct hash_ipportip6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&

View File

@@ -62,7 +62,8 @@ struct hash_ipportnet4_telem {
static inline bool static inline bool
hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
const struct hash_ipportnet4_elem *ip2) const struct hash_ipportnet4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip && return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 && ip1->ip2 == ip2->ip2 &&
@@ -335,7 +336,8 @@ struct hash_ipportnet6_telem {
static inline bool static inline bool
hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
const struct hash_ipportnet6_elem *ip2) const struct hash_ipportnet6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&

View File

@@ -58,7 +58,8 @@ struct hash_net4_telem {
static inline bool static inline bool
hash_net4_data_equal(const struct hash_net4_elem *ip1, hash_net4_data_equal(const struct hash_net4_elem *ip1,
const struct hash_net4_elem *ip2) const struct hash_net4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr; return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
} }
@@ -249,7 +250,8 @@ struct hash_net6_telem {
static inline bool static inline bool
hash_net6_data_equal(const struct hash_net6_elem *ip1, hash_net6_data_equal(const struct hash_net6_elem *ip1,
const struct hash_net6_elem *ip2) const struct hash_net6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr; ip1->cidr == ip2->cidr;

View File

@@ -99,7 +99,7 @@ iface_test(struct rb_root *root, const char **iface)
while (n) { while (n) {
const char *d = iface_data(n); const char *d = iface_data(n);
int res = ifname_compare(*iface, d); long res = ifname_compare(*iface, d);
if (res < 0) if (res < 0)
n = n->rb_left; n = n->rb_left;
@@ -121,7 +121,7 @@ iface_add(struct rb_root *root, const char **iface)
while (*n) { while (*n) {
char *ifname = iface_data(*n); char *ifname = iface_data(*n);
int res = ifname_compare(*iface, ifname); long res = ifname_compare(*iface, ifname);
p = *n; p = *n;
if (res < 0) if (res < 0)
@@ -159,31 +159,42 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
/* The type variant functions: IPv4 */ /* The type variant functions: IPv4 */
/* Member elements without timeout */ struct hash_netiface4_elem_hashed {
struct hash_netiface4_elem {
__be32 ip; __be32 ip;
const char *iface;
u8 physdev; u8 physdev;
u8 cidr; u8 cidr;
u16 padding; u16 padding;
}; };
#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
/* Member elements without timeout */
struct hash_netiface4_elem {
__be32 ip;
u8 physdev;
u8 cidr;
u16 padding;
const char *iface;
};
/* Member elements with timeout support */ /* Member elements with timeout support */
struct hash_netiface4_telem { struct hash_netiface4_telem {
__be32 ip; __be32 ip;
const char *iface;
u8 physdev; u8 physdev;
u8 cidr; u8 cidr;
u16 padding; u16 padding;
const char *iface;
unsigned long timeout; unsigned long timeout;
}; };
static inline bool static inline bool
hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
const struct hash_netiface4_elem *ip2) const struct hash_netiface4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip && return ip1->ip == ip2->ip &&
ip1->cidr == ip2->cidr && ip1->cidr == ip2->cidr &&
(++*multi) &&
ip1->physdev == ip2->physdev && ip1->physdev == ip2->physdev &&
ip1->iface == ip2->iface; ip1->iface == ip2->iface;
} }
@@ -257,6 +268,7 @@ nla_put_failure:
#define IP_SET_HASH_WITH_NETS #define IP_SET_HASH_WITH_NETS
#define IP_SET_HASH_WITH_RBTREE #define IP_SET_HASH_WITH_RBTREE
#define IP_SET_HASH_WITH_MULTI
#define PF 4 #define PF 4
#define HOST_MASK 32 #define HOST_MASK 32
@@ -424,29 +436,40 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
/* The type variant functions: IPv6 */ /* The type variant functions: IPv6 */
struct hash_netiface6_elem { struct hash_netiface6_elem_hashed {
union nf_inet_addr ip; union nf_inet_addr ip;
const char *iface;
u8 physdev; u8 physdev;
u8 cidr; u8 cidr;
u16 padding; u16 padding;
}; };
struct hash_netiface6_telem { #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
struct hash_netiface6_elem {
union nf_inet_addr ip; union nf_inet_addr ip;
const char *iface;
u8 physdev; u8 physdev;
u8 cidr; u8 cidr;
u16 padding; u16 padding;
const char *iface;
};
struct hash_netiface6_telem {
union nf_inet_addr ip;
u8 physdev;
u8 cidr;
u16 padding;
const char *iface;
unsigned long timeout; unsigned long timeout;
}; };
static inline bool static inline bool
hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
const struct hash_netiface6_elem *ip2) const struct hash_netiface6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr && ip1->cidr == ip2->cidr &&
(++*multi) &&
ip1->physdev == ip2->physdev && ip1->physdev == ip2->physdev &&
ip1->iface == ip2->iface; ip1->iface == ip2->iface;
} }
@@ -681,6 +704,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->maxelem = maxelem; h->maxelem = maxelem;
get_random_bytes(&h->initval, sizeof(h->initval)); get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT; h->timeout = IPSET_NO_TIMEOUT;
h->ahash_max = AHASH_MAX_SIZE;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
h->table = ip_set_alloc( h->table = ip_set_alloc(

View File

@@ -59,7 +59,8 @@ struct hash_netport4_telem {
static inline bool static inline bool
hash_netport4_data_equal(const struct hash_netport4_elem *ip1, hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
const struct hash_netport4_elem *ip2) const struct hash_netport4_elem *ip2,
u32 *multi)
{ {
return ip1->ip == ip2->ip && return ip1->ip == ip2->ip &&
ip1->port == ip2->port && ip1->port == ip2->port &&
@@ -300,7 +301,8 @@ struct hash_netport6_telem {
static inline bool static inline bool
hash_netport6_data_equal(const struct hash_netport6_elem *ip1, hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
const struct hash_netport6_elem *ip2) const struct hash_netport6_elem *ip2,
u32 *multi)
{ {
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port && ip1->port == ip2->port &&

View File

@@ -767,7 +767,11 @@ the interface is flagged with \fBphysdev:\fR, the interface is interpreted
as the incoming/outgoing bridge port. as the incoming/outgoing bridge port.
.PP .PP
The lookup time grows linearly with the number of the different prefix The lookup time grows linearly with the number of the different prefix
values added to the set. values added to the set.
.PP
The internal restriction of the \fBhash:net,iface\fR set type is that
the same network prefix cannot be stored with more than 64 different interfaces
in a single set.
.PP .PP
Examples: Examples:
.IP .IP