mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-06 20:55:13 +02:00
Merge branch 'ipset'
Conflicts: doc/changelog.txt
This commit is contained in:
@@ -5,6 +5,7 @@ HEAD
|
||||
- xt_TEE: abort build when the feature is already provided by mainline
|
||||
- xt_psd: restore functionality with UDP
|
||||
- xt_psd: support UDPLITE
|
||||
- update to ipset 6.8
|
||||
|
||||
|
||||
v1.37 (2011-06-25)
|
||||
|
@@ -28,7 +28,32 @@
|
||||
/* Number of elements to store in an initial array block */
|
||||
#define AHASH_INIT_SIZE 4
|
||||
/* 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 */
|
||||
struct hbucket {
|
||||
@@ -60,6 +85,9 @@ struct ip_set_hash {
|
||||
u32 timeout; /* timeout value, if enabled */
|
||||
struct timer_list gc; /* garbage collection when timeout enabled */
|
||||
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
|
||||
u8 netmask; /* netmask value for subnets to store */
|
||||
#endif
|
||||
@@ -211,12 +239,16 @@ ip_set_hash_destroy(struct ip_set *set)
|
||||
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 */
|
||||
|
||||
#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 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:
|
||||
* we spare the maintenance of the internal counters. */
|
||||
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) {
|
||||
void *tmp;
|
||||
|
||||
if (n->size >= AHASH_MAX_SIZE)
|
||||
if (n->size >= ahash_max)
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
|
||||
@@ -335,7 +368,7 @@ retry:
|
||||
for (j = 0; j < n->pos; j++) {
|
||||
data = ahash_data(n, j);
|
||||
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) {
|
||||
read_unlock_bh(&set->lock);
|
||||
ahash_destroy(t);
|
||||
@@ -359,7 +392,7 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
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,
|
||||
@@ -372,7 +405,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
const struct type_pf_elem *d = value;
|
||||
struct hbucket *n;
|
||||
int i, ret = 0;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
|
||||
if (h->elements >= h->maxelem)
|
||||
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);
|
||||
n = hbucket(t, key);
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = type_pf_elem_add(n, value);
|
||||
TUNE_AHASH_MAX(h, multi);
|
||||
ret = type_pf_elem_add(n, value, AHASH_MAX(h));
|
||||
if (ret != 0) {
|
||||
if (ret == -EAGAIN)
|
||||
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;
|
||||
int i;
|
||||
struct type_pf_elem *data;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
|
||||
key = HKEY(value, h->initval, t->htable_bits);
|
||||
n = hbucket(t, key);
|
||||
for (i = 0; i < n->pos; i++) {
|
||||
data = ahash_data(n, i);
|
||||
if (!type_pf_data_equal(data, d))
|
||||
if (!type_pf_data_equal(data, d, &multi))
|
||||
continue;
|
||||
if (i != n->pos - 1)
|
||||
/* 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;
|
||||
const struct type_pf_elem *data;
|
||||
int i, j = 0;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
u8 host_mask = SET_HOST_MASK(set->family);
|
||||
|
||||
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);
|
||||
key = HKEY(d, h->initval, t->htable_bits);
|
||||
n = hbucket(t, key);
|
||||
for (i = 0; i < n->pos; i++) {
|
||||
data = ahash_data(n, i);
|
||||
if (type_pf_data_equal(data, d))
|
||||
if (type_pf_data_equal(data, d, &multi))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -490,7 +523,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
|
||||
struct hbucket *n;
|
||||
const struct type_pf_elem *data;
|
||||
int i;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
/* 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);
|
||||
for (i = 0; i < n->pos; i++) {
|
||||
data = ahash_data(n, i);
|
||||
if (type_pf_data_equal(data, d))
|
||||
if (type_pf_data_equal(data, d, &multi))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -660,14 +693,14 @@ type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
|
||||
|
||||
static int
|
||||
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;
|
||||
|
||||
if (n->pos >= n->size) {
|
||||
void *tmp;
|
||||
|
||||
if (n->size >= AHASH_MAX_SIZE)
|
||||
if (n->size >= ahash_max)
|
||||
/* Trigger rehashing */
|
||||
return -EAGAIN;
|
||||
|
||||
@@ -772,7 +805,7 @@ retry:
|
||||
for (j = 0; j < n->pos; j++) {
|
||||
data = ahash_tdata(n, j);
|
||||
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));
|
||||
if (ret < 0) {
|
||||
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;
|
||||
struct hbucket *n;
|
||||
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;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
|
||||
if (h->elements >= h->maxelem)
|
||||
/* 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);
|
||||
for (i = 0; i < n->pos; 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)
|
||||
j = i;
|
||||
else {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto out;
|
||||
}
|
||||
} else if (j == AHASH_MAX_SIZE + 1 &&
|
||||
} else if (j == AHASH_MAX(h) + 1 &&
|
||||
type_pf_data_expired(data))
|
||||
j = i;
|
||||
}
|
||||
if (j != AHASH_MAX_SIZE + 1) {
|
||||
if (j != AHASH_MAX(h) + 1) {
|
||||
data = ahash_tdata(n, j);
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
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);
|
||||
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 == -EAGAIN)
|
||||
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;
|
||||
int i;
|
||||
struct type_pf_elem *data;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
|
||||
key = HKEY(value, h->initval, t->htable_bits);
|
||||
n = hbucket(t, key);
|
||||
for (i = 0; i < n->pos; i++) {
|
||||
data = ahash_tdata(n, i);
|
||||
if (!type_pf_data_equal(data, d))
|
||||
if (!type_pf_data_equal(data, d, &multi))
|
||||
continue;
|
||||
if (type_pf_data_expired(data))
|
||||
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 hbucket *n;
|
||||
int i, j = 0;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
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);
|
||||
key = HKEY(d, h->initval, t->htable_bits);
|
||||
n = hbucket(t, key);
|
||||
for (i = 0; i < n->pos; 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);
|
||||
}
|
||||
}
|
||||
@@ -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 hbucket *n;
|
||||
int i;
|
||||
u32 key;
|
||||
u32 key, multi = 0;
|
||||
|
||||
#ifdef IP_SET_HASH_WITH_NETS
|
||||
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);
|
||||
for (i = 0; i < n->pos; 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 0;
|
||||
@@ -1054,6 +1088,8 @@ type_pf_gc_init(struct ip_set *set)
|
||||
IPSET_GC_PERIOD(h->timeout));
|
||||
}
|
||||
|
||||
#undef HKEY_DATALEN
|
||||
#undef HKEY
|
||||
#undef type_pf_data_equal
|
||||
#undef type_pf_data_isnull
|
||||
#undef type_pf_data_copy
|
||||
|
@@ -53,7 +53,8 @@ struct hash_ip4_telem {
|
||||
|
||||
static inline bool
|
||||
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;
|
||||
}
|
||||
@@ -225,7 +226,8 @@ struct hash_ip6_telem {
|
||||
|
||||
static inline bool
|
||||
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;
|
||||
}
|
||||
|
@@ -60,7 +60,8 @@ struct hash_ipport4_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->port == ip2->port &&
|
||||
@@ -276,7 +277,8 @@ struct hash_ipport6_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->port == ip2->port &&
|
||||
|
@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->ip2 == ip2->ip2 &&
|
||||
@@ -286,7 +287,8 @@ struct hash_ipportip6_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
|
||||
|
@@ -62,7 +62,8 @@ struct hash_ipportnet4_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->ip2 == ip2->ip2 &&
|
||||
@@ -335,7 +336,8 @@ struct hash_ipportnet6_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
|
||||
|
@@ -58,7 +58,8 @@ struct hash_net4_telem {
|
||||
|
||||
static inline bool
|
||||
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;
|
||||
}
|
||||
@@ -249,7 +250,8 @@ struct hash_net6_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->cidr == ip2->cidr;
|
||||
|
@@ -99,7 +99,7 @@ iface_test(struct rb_root *root, const char **iface)
|
||||
|
||||
while (n) {
|
||||
const char *d = iface_data(n);
|
||||
int res = ifname_compare(*iface, d);
|
||||
long res = ifname_compare(*iface, d);
|
||||
|
||||
if (res < 0)
|
||||
n = n->rb_left;
|
||||
@@ -121,7 +121,7 @@ iface_add(struct rb_root *root, const char **iface)
|
||||
|
||||
while (*n) {
|
||||
char *ifname = iface_data(*n);
|
||||
int res = ifname_compare(*iface, ifname);
|
||||
long res = ifname_compare(*iface, ifname);
|
||||
|
||||
p = *n;
|
||||
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 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_netiface4_elem {
|
||||
struct hash_netiface4_elem_hashed {
|
||||
__be32 ip;
|
||||
const char *iface;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
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 */
|
||||
struct hash_netiface4_telem {
|
||||
__be32 ip;
|
||||
const char *iface;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
const char *iface;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->cidr == ip2->cidr &&
|
||||
(++*multi) &&
|
||||
ip1->physdev == ip2->physdev &&
|
||||
ip1->iface == ip2->iface;
|
||||
}
|
||||
@@ -257,6 +268,7 @@ nla_put_failure:
|
||||
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
#define IP_SET_HASH_WITH_RBTREE
|
||||
#define IP_SET_HASH_WITH_MULTI
|
||||
|
||||
#define PF 4
|
||||
#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 */
|
||||
|
||||
struct hash_netiface6_elem {
|
||||
struct hash_netiface6_elem_hashed {
|
||||
union nf_inet_addr ip;
|
||||
const char *iface;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
u16 padding;
|
||||
};
|
||||
|
||||
struct hash_netiface6_telem {
|
||||
#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
|
||||
|
||||
struct hash_netiface6_elem {
|
||||
union nf_inet_addr ip;
|
||||
const char *iface;
|
||||
u8 physdev;
|
||||
u8 cidr;
|
||||
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;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->cidr == ip2->cidr &&
|
||||
(++*multi) &&
|
||||
ip1->physdev == ip2->physdev &&
|
||||
ip1->iface == ip2->iface;
|
||||
}
|
||||
@@ -681,6 +704,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
h->ahash_max = AHASH_MAX_SIZE;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
|
@@ -59,7 +59,8 @@ struct hash_netport4_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->port == ip2->port &&
|
||||
@@ -300,7 +301,8 @@ struct hash_netport6_telem {
|
||||
|
||||
static inline bool
|
||||
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 &&
|
||||
ip1->port == ip2->port &&
|
||||
|
@@ -767,7 +767,11 @@ the interface is flagged with \fBphysdev:\fR, the interface is interpreted
|
||||
as the incoming/outgoing bridge port.
|
||||
.PP
|
||||
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
|
||||
Examples:
|
||||
.IP
|
||||
|
Reference in New Issue
Block a user