All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: [PATCH 04/18] netfilter: ipset: Unified bitmap type generation
Date: Mon, 29 Apr 2013 20:22:10 +0200	[thread overview]
Message-ID: <1367259744-8922-5-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1367259744-8922-1-git-send-email-pablo@netfilter.org>

From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/ipset/ip_set_bitmap.h |    6 +
 net/netfilter/ipset/ip_set_bitmap_gen.h       |  265 +++++++++++++++++++++++++
 2 files changed, 271 insertions(+)
 create mode 100644 net/netfilter/ipset/ip_set_bitmap_gen.h

diff --git a/include/linux/netfilter/ipset/ip_set_bitmap.h b/include/linux/netfilter/ipset/ip_set_bitmap.h
index 1a30646..5e4662a 100644
--- a/include/linux/netfilter/ipset/ip_set_bitmap.h
+++ b/include/linux/netfilter/ipset/ip_set_bitmap.h
@@ -5,6 +5,12 @@
 
 #define IPSET_BITMAP_MAX_RANGE	0x0000FFFF
 
+enum {
+	IPSET_ADD_FAILED = 1,
+	IPSET_ADD_STORE_PLAIN_TIMEOUT,
+	IPSET_ADD_START_STORED_TIMEOUT,
+};
+
 /* Common functions */
 
 static inline u32
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
new file mode 100644
index 0000000..b993159
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -0,0 +1,265 @@
+/* Copyright (C) 2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __IP_SET_BITMAP_IP_GEN_H
+#define __IP_SET_BITMAP_IP_GEN_H
+
+#define CONCAT(a, b)		a##b
+#define TOKEN(a,b)		CONCAT(a, b)
+
+#define mtype_do_test		TOKEN(MTYPE, _do_test)
+#define mtype_gc_test		TOKEN(MTYPE, _gc_test)
+#define mtype_is_filled		TOKEN(MTYPE, _is_filled)
+#define mtype_do_add		TOKEN(MTYPE, _do_add)
+#define mtype_do_del		TOKEN(MTYPE, _do_del)
+#define mtype_do_list		TOKEN(MTYPE, _do_list)
+#define mtype_do_head		TOKEN(MTYPE, _do_head)
+#define mtype_adt_elem		TOKEN(MTYPE, _adt_elem)
+#define mtype_add_timeout	TOKEN(MTYPE, _add_timeout)
+#define mtype_gc_init		TOKEN(MTYPE, _gc_init)
+#define mtype_kadt		TOKEN(MTYPE, _kadt)
+#define mtype_uadt		TOKEN(MTYPE, _uadt)
+#define mtype_destroy		TOKEN(MTYPE, _destroy)
+#define mtype_flush		TOKEN(MTYPE, _flush)
+#define mtype_head		TOKEN(MTYPE, _head)
+#define mtype_same_set		TOKEN(MTYPE, _same_set)
+#define mtype_elem		TOKEN(MTYPE, _elem)
+#define mtype_test		TOKEN(MTYPE, _test)
+#define mtype_add		TOKEN(MTYPE, _add)
+#define mtype_del		TOKEN(MTYPE, _del)
+#define mtype_list		TOKEN(MTYPE, _list)
+#define mtype_gc		TOKEN(MTYPE, _gc)
+#define mtype			MTYPE
+
+#define ext_timeout(e, m)	\
+	(unsigned long *)((e) + (m)->offset[IPSET_OFFSET_TIMEOUT])
+#define get_ext(map, id)	((map)->extensions + (map)->dsize * (id))
+
+static void
+mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
+{
+	struct mtype *map = set->data;
+
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = gc;
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+static void
+mtype_destroy(struct ip_set *set)
+{
+	struct mtype *map = set->data;
+
+	if (SET_WITH_TIMEOUT(set))
+		del_timer_sync(&map->gc);
+
+	ip_set_free(map->members);
+	if (map->dsize)
+		ip_set_free(map->extensions);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void
+mtype_flush(struct ip_set *set)
+{
+	struct mtype *map = set->data;
+
+	memset(map->members, 0, map->memsize);
+}
+
+static int
+mtype_head(struct ip_set *set, struct sk_buff *skb)
+{
+	const struct mtype *map = set->data;
+	struct nlattr *nested;
+
+	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+	if (!nested)
+		goto nla_put_failure;
+	if (mtype_do_head(skb, map) ||
+	    nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
+	    nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
+			  htonl(sizeof(*map) +
+				map->memsize +
+				map->dsize * map->elements)) ||
+	    (SET_WITH_TIMEOUT(set) &&
+	     nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
+		goto nla_put_failure;
+	ipset_nest_end(skb, nested);
+
+	return 0;
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int
+mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+	   struct ip_set_ext *mext, u32 flags)
+{
+	struct mtype *map = set->data;
+	const struct mtype_adt_elem *e = value;
+	void *x = get_ext(map, e->id);
+	int ret = mtype_do_test(e, map);
+
+	if (ret <= 0)
+		return ret;
+	if (SET_WITH_TIMEOUT(set) &&
+	    ip_set_timeout_expired(ext_timeout(x, map)))
+		return 0;
+	return 1;
+}
+
+static int
+mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+	  struct ip_set_ext *mext, u32 flags)
+{
+	struct mtype *map = set->data;
+	const struct mtype_adt_elem *e = value;
+	void *x = get_ext(map, e->id);
+	int ret = mtype_do_add(e, map, flags);
+
+	if (ret == IPSET_ADD_FAILED) {
+		if (SET_WITH_TIMEOUT(set) &&
+		    ip_set_timeout_expired(ext_timeout(x, map)))
+			ret = 0;
+		else if (!(flags & IPSET_FLAG_EXIST))
+			return -IPSET_ERR_EXIST;
+	}
+
+	if (SET_WITH_TIMEOUT(set))
+#ifdef IP_SET_BITMAP_STORED_TIMEOUT
+		mtype_add_timeout(ext_timeout(x, map), e, ext, map, ret);
+#else
+		ip_set_timeout_set(ext_timeout(x, map), ext->timeout);
+#endif
+
+	return 0;
+}
+
+static int
+mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+	  struct ip_set_ext *mext, u32 flags)
+{
+	struct mtype *map = set->data;
+	const struct mtype_adt_elem *e = value;
+	const void *x = get_ext(map, e->id);
+
+	if (mtype_do_del(e, map) ||
+	    (SET_WITH_TIMEOUT(set) &&
+	     ip_set_timeout_expired(ext_timeout(x, map))))
+		return -IPSET_ERR_EXIST;
+
+	return 0;
+}
+
+static int
+mtype_list(const struct ip_set *set,
+	   struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct mtype *map = set->data;
+	struct nlattr *adt, *nested;
+	void *x;
+	u32 id, first = cb->args[2];
+
+	adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!adt)
+		return -EMSGSIZE;
+	for (; cb->args[2] < map->elements; cb->args[2]++) {
+		id = cb->args[2];
+		x = get_ext(map, id);
+		if (!test_bit(id, map->members) ||
+		    (SET_WITH_TIMEOUT(set) &&
+#ifdef IP_SET_BITMAP_STORED_TIMEOUT
+		     mtype_is_filled((const struct mtype_elem *) x) &&
+#endif
+		     ip_set_timeout_expired(ext_timeout(x, map))))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, adt);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		if (mtype_do_list(skb, map, id))
+			goto nla_put_failure;
+		if (SET_WITH_TIMEOUT(set)) {
+#ifdef IP_SET_BITMAP_STORED_TIMEOUT
+			if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
+					  htonl(ip_set_timeout_stored(map, id,
+							ext_timeout(x, map)))))
+				goto nla_put_failure;
+#else
+			if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
+					  htonl(ip_set_timeout_get(
+							ext_timeout(x, map)))))
+				goto nla_put_failure;
+#endif
+		}
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, adt);
+
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, adt);
+	if (unlikely(id == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+static void
+mtype_gc(unsigned long ul_set)
+{
+	struct ip_set *set = (struct ip_set *) ul_set;
+	struct mtype *map = set->data;
+	const void *x;
+	u32 id;
+
+	/* We run parallel with other readers (test element)
+	 * but adding/deleting new entries is locked out */
+	read_lock_bh(&set->lock);
+	for (id = 0; id < map->elements; id++)
+		if (mtype_gc_test(id, map)) {
+			x = get_ext(map, id);
+			if (ip_set_timeout_expired(ext_timeout(x, map)))
+				clear_bit(id, map->members);
+		}
+	read_unlock_bh(&set->lock);
+
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+static const struct ip_set_type_variant mtype = {
+	.kadt	= mtype_kadt,
+	.uadt	= mtype_uadt,
+	.adt	= {
+		[IPSET_ADD] = mtype_add,
+		[IPSET_DEL] = mtype_del,
+		[IPSET_TEST] = mtype_test,
+	},
+	.destroy = mtype_destroy,
+	.flush	= mtype_flush,
+	.head	= mtype_head,
+	.list	= mtype_list,
+	.same_set = mtype_same_set,
+};
+
+#endif /* __IP_SET_BITMAP_IP_GEN_H */
-- 
1.7.10.4

  parent reply	other threads:[~2013-04-29 18:22 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-29 18:22 [PATCH 00/18] netfilter updates for net-next (try 2) Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 01/18] netfilter: ipset: Make possible to test elements marked with nomatch Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 02/18] netfilter: ipset: Move often used IPv6 address masking function to header file Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 03/18] netfilter: ipset: Introduce extensions to elements in the core Pablo Neira Ayuso
2013-04-29 18:22 ` Pablo Neira Ayuso [this message]
2013-04-30  8:49   ` [PATCH 04/18] netfilter: ipset: Unified bitmap type generation David Laight
2013-04-30  9:19     ` Jozsef Kadlecsik
2013-04-29 18:22 ` [PATCH 05/18] netfilter: ipset: Bitmap types using the unified code base Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 06/18] netfilter: ipset: Unified hash type generation Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 07/18] netfilter: ipset: Hash types using the unified code base Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 08/18] netfilter: ipset: list:set type using the extension interface Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 09/18] netfilter: ipset: Introduce the counter extension in the core Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 10/18] netfilter: ipset: The bitmap types with counter support Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 11/18] netfilter: ipset: The hash " Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 12/18] netfilter: ipset: The list:set type " Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 13/18] netfilter: ipset: set match: add support to match the counters Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 14/18] netfilter: nf_queue: move device refcount bump to extra function Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 15/18] netfilter: move skb_gso_segment into nfnetlink_queue module Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 16/18] netfilter: nfnetlink_queue: add skb info attribute Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 17/18] netfilter: nfnetlink_queue: avoid expensive gso segmentation and checksum fixup Pablo Neira Ayuso
2013-04-29 18:22 ` [PATCH 18/18] sctp: Correct type and usage of sctp_end_cksum() Pablo Neira Ayuso
2013-04-29 19:17 ` [PATCH 00/18] netfilter updates for net-next (try 2) David Miller
  -- strict thread matches above, loose matches on Subject: below --
2013-04-27 18:58 [PATCH 00/18] netfilter updates for net-next Pablo Neira Ayuso
2013-04-27 18:58 ` [PATCH 04/18] netfilter: ipset: Unified bitmap type generation Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1367259744-8922-5-git-send-email-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.