]> granicus.if.org Git - ipset/commitdiff
Prepare ipset to support multiple networks for hash types
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Wed, 4 Sep 2013 14:56:12 +0000 (16:56 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Wed, 4 Sep 2013 14:56:12 +0000 (16:56 +0200)
In order to support hash:net,net, hash:net,port,net etc. types,
arrays are introduced for the book-keeping of existing cidr sizes
and network numbers in a set.

kernel/include/linux/netfilter/ipset/ip_set.h
kernel/net/netfilter/ipset/ip_set_hash_gen.h
kernel/net/netfilter/ipset/ip_set_hash_ipportnet.c
kernel/net/netfilter/ipset/ip_set_hash_net.c
kernel/net/netfilter/ipset/ip_set_hash_netiface.c
kernel/net/netfilter/ipset/ip_set_hash_netport.c

index f974f35578772d03abc8bfbd30866626825064d5..03f99d61ae1e7623515b0d8c18d211fc2c895b63 100644 (file)
@@ -399,6 +399,8 @@ bitmap_bytes(u32 a, u32 b)
        { .bytes = ULLONG_MAX, .packets = ULLONG_MAX,   \
          .timeout = (map)->timeout }
 
+#define IP_SET_INIT_CIDR(a, b) ((a) ? (a) : (b))
+
 #define IPSET_CONCAT(a, b)             a##b
 #define IPSET_TOKEN(a, b)              IPSET_CONCAT(a, b)
 
index c69407981cf22a18d614705793fc89c6f9da0a40..596fcb6454bb1834b9af3da7a605733796a8a2bc 100644 (file)
@@ -77,10 +77,14 @@ struct htable {
 
 #define hbucket(h, i)          (&((h)->bucket[i]))
 
+#ifndef IPSET_NET_COUNT
+#define IPSET_NET_COUNT                1
+#endif
+
 /* Book-keeping of the prefixes added to the set */
 struct net_prefixes {
-       u8 cidr;                /* the different cidr values in the set */
-       u32 nets;               /* number of elements per cidr */
+       u32 nets[IPSET_NET_COUNT]; /* number of elements per cidr */
+       u8 cidr[IPSET_NET_COUNT];  /* the different cidr values in the set */
 };
 
 /* Compute the hash table size */
@@ -165,13 +169,13 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize)
 #define SET_HOST_MASK(family)  (family == AF_INET ? 32 : 128)
 
 #ifdef IP_SET_HASH_WITH_MULTI
-#define NETS_LENGTH(family)    (SET_HOST_MASK(family) + 1)
+#define NLEN(family)           (SET_HOST_MASK(family) + 1)
 #else
-#define NETS_LENGTH(family)    SET_HOST_MASK(family)
+#define NLEN(family)           SET_HOST_MASK(family)
 #endif
 
 #else
-#define NETS_LENGTH(family)    0
+#define NLEN(family)           0
 #endif /* IP_SET_HASH_WITH_NETS */
 
 #define ext_timeout(e, h)      \
@@ -296,46 +300,46 @@ struct htype {
 /* Network cidr size book keeping when the hash stores different
  * sized networks */
 static void
-mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length)
+mtype_add_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
 {
        int i, j;
 
        /* Add in increasing prefix order, so larger cidr first */
-       for (i = 0, j = -1; i < nets_length && h->nets[i].nets; i++) {
+       for (i = 0, j = -1; i < nets_length && h->nets[i].nets[n]; i++) {
                if (j != -1)
                        continue;
-               else if (h->nets[i].cidr < cidr)
+               else if (h->nets[i].cidr[n] < cidr)
                        j = i;
-               else if (h->nets[i].cidr == cidr) {
-                       h->nets[i].nets++;
+               else if (h->nets[i].cidr[n] == cidr) {
+                       h->nets[i].nets[n]++;
                        return;
                }
        }
        if (j != -1) {
                for (; i > j; i--) {
-                       h->nets[i].cidr = h->nets[i - 1].cidr;
-                       h->nets[i].nets = h->nets[i - 1].nets;
+                       h->nets[i].cidr[n] = h->nets[i - 1].cidr[n];
+                       h->nets[i].nets[n] = h->nets[i - 1].nets[n];
                }
        }
-       h->nets[i].cidr = cidr;
-       h->nets[i].nets = 1;
+       h->nets[i].cidr[n] = cidr;
+       h->nets[i].nets[n] = 1;
 }
 
 static void
-mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length)
+mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
 {
        u8 i, j;
 
-       for (i = 0; i < nets_length - 1 && h->nets[i].cidr != cidr; i++)
+       for (i = 0; i < nets_length - 1 && h->nets[i].cidr[n] != cidr; i++)
                ;
-       h->nets[i].nets--;
+       h->nets[i].nets[n]--;
 
-       if (h->nets[i].nets != 0)
+       if (h->nets[i].nets[n] != 0)
                return;
 
-       for (j = i; j < nets_length - 1 && h->nets[j].nets; j++) {
-               h->nets[j].cidr = h->nets[j + 1].cidr;
-               h->nets[j].nets = h->nets[j + 1].nets;
+       for (j = i; j < nets_length - 1 && h->nets[j].nets[n]; j++) {
+               h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
+               h->nets[j].nets[n] = h->nets[j + 1].nets[n];
        }
 }
 #endif
@@ -378,8 +382,7 @@ mtype_flush(struct ip_set *set)
                }
        }
 #ifdef IP_SET_HASH_WITH_NETS
-       memset(h->nets, 0, sizeof(struct net_prefixes)
-                          * NETS_LENGTH(set->family));
+       memset(h->nets, 0, sizeof(struct net_prefixes) * NLEN(set->family));
 #endif
        h->elements = 0;
 }
@@ -455,7 +458,7 @@ mtype_expire(struct htype *h, u8 nets_length, size_t dsize)
                                pr_debug("expired %u/%u\n", i, j);
 #ifdef IP_SET_HASH_WITH_NETS
                                mtype_del_cidr(h, CIDR(data->cidr),
-                                              nets_length);
+                                              nets_length, 0);
 #endif
                                if (j != n->pos - 1)
                                        /* Not last one */
@@ -490,7 +493,7 @@ mtype_gc(unsigned long ul_set)
 
        pr_debug("called\n");
        write_lock_bh(&set->lock);
-       mtype_expire(h, NETS_LENGTH(set->family), h->dsize);
+       mtype_expire(h, NLEN(set->family), h->dsize);
        write_unlock_bh(&set->lock);
 
        h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
@@ -519,8 +522,7 @@ mtype_resize(struct ip_set *set, bool retried)
        if (SET_WITH_TIMEOUT(set) && !retried) {
                i = h->elements;
                write_lock_bh(&set->lock);
-               mtype_expire(set->data, NETS_LENGTH(set->family),
-                            h->dsize);
+               mtype_expire(set->data, NLEN(set->family), h->dsize);
                write_unlock_bh(&set->lock);
                if (h->elements < i)
                        return 0;
@@ -603,7 +605,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
 
        if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem)
                /* FIXME: when set is full, we slow down here */
-               mtype_expire(h, NETS_LENGTH(set->family), h->dsize);
+               mtype_expire(h, NLEN(set->family), h->dsize);
 
        if (h->elements >= h->maxelem) {
                if (net_ratelimit())
@@ -641,8 +643,8 @@ reuse_slot:
                /* Fill out reused slot */
                data = ahash_data(n, j, h->dsize);
 #ifdef IP_SET_HASH_WITH_NETS
-               mtype_del_cidr(h, CIDR(data->cidr), NETS_LENGTH(set->family));
-               mtype_add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
+               mtype_del_cidr(h, CIDR(data->cidr), NLEN(set->family), 0);
+               mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0);
 #endif
        } else {
                /* Use/create a new slot */
@@ -655,7 +657,7 @@ reuse_slot:
                }
                data = ahash_data(n, n->pos++, h->dsize);
 #ifdef IP_SET_HASH_WITH_NETS
-               mtype_add_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
+               mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0);
 #endif
                h->elements++;
        }
@@ -707,7 +709,7 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
                n->pos--;
                h->elements--;
 #ifdef IP_SET_HASH_WITH_NETS
-               mtype_del_cidr(h, CIDR(d->cidr), NETS_LENGTH(set->family));
+               mtype_del_cidr(h, CIDR(d->cidr), NLEN(set->family), 0);
 #endif
                if (n->pos + AHASH_INIT_SIZE < n->size) {
                        void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
@@ -756,11 +758,11 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
        struct mtype_elem *data;
        int i, j = 0;
        u32 key, multi = 0;
-       u8 nets_length = NETS_LENGTH(set->family);
+       u8 nets_length = NLEN(set->family);
 
        pr_debug("test by nets\n");
-       for (; j < nets_length && h->nets[j].nets && !multi; j++) {
-               mtype_data_netmask(d, h->nets[j].cidr);
+       for (; j < nets_length && h->nets[j].nets[0] && !multi; j++) {
+               mtype_data_netmask(d, h->nets[j].cidr[0]);
                key = HKEY(d, h->initval, t->htable_bits);
                n = hbucket(t, key);
                for (i = 0; i < n->pos; i++) {
@@ -835,7 +837,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
        size_t memsize;
 
        t = rcu_dereference_bh_nfnl(h->table);
-       memsize = mtype_ahash_memsize(h, t, NETS_LENGTH(set->family));
+       memsize = mtype_ahash_memsize(h, t, NLEN(set->family));
 
        nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
        if (!nested)
index f111558c459713ed90a9b9d9e08c3324bd31b690..6ce5a8e2c44e368f2d3681e4e60730d44f0040ab 100644 (file)
@@ -170,7 +170,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
        const struct hash_ipportnet *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 
@@ -454,7 +454,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
        const struct hash_ipportnet *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet6_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 
index 0a64dad156d928a20b09ce7f13c77db7c36a59b4..ec1c7dc10489280716cee1ae244c67353d2556a2 100644 (file)
@@ -143,7 +143,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
        const struct hash_net *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net4_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 
@@ -338,7 +338,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
        const struct hash_net *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net6_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 
index 846371b08630d04162237c0c72eba410fb242c82..814b4e31a7f8e053e2d931e76d817cd928c23ce0 100644 (file)
@@ -265,7 +265,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct hash_netiface *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netiface4_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
                .elem = 1,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
@@ -534,7 +534,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
        struct hash_netiface *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netiface6_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
                .elem = 1,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
index d98a685cd916f262625fddfd746b2cb7d55d7d6b..3bd923d3f1797df92e48f9ccd7c661b3be75543f 100644 (file)
@@ -162,7 +162,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
        const struct hash_netport *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netport4_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 
@@ -407,7 +407,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
        const struct hash_netport *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netport6_elem e = {
-               .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1,
+               .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
        };
        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);