All of lore.kernel.org
 help / color / mirror / Atom feed
* Add tcindex to conntrack and add netfilter target/matches
@ 2015-12-16  0:20 Luuk Paulussen
  2015-12-16  0:20 ` [PATCH] " Luuk Paulussen
  0 siblings, 1 reply; 5+ messages in thread
From: Luuk Paulussen @ 2015-12-16  0:20 UTC (permalink / raw)
  To: netdev; +Cc: kyeong.yoo, matt.bennett


I recently posted this patch to the netfilter-devel and lartc mailing lists.  The
feedback I have had so far has mostly been questions around how we would use this, and some
suggestions that don't solve the issues.  I haven't had any negative feedback.

The key use case is to mark first packet in flows in either direction using all xtables rules
and then save the mark into the connection.  For subsequent packets in the flow, restore mark
and skip full processing.  Flows that don't match any rule are still marked with a default mark
so that future packets in the flow don't have to go through all of the rules.

Comments/suggestions so far:
 - Use/extend cls_flow to handle tc_index from connection directly. - cls_flow can't
   be used with class-based qdiscs, and also being able to restore with a mask is
   useful for separating request/response from flow.  Also tcindex filter already exists. (This
   suggestion implies that tc_index will be added to the connection information)
 - use CLASSIFY target in xtables and use cls_flow to match prioirity. - CLASSIFY doesn't allow
   the desired performance benefits of restoring mark from connection and we can't use cls_flow.
 - cls_bfp supports tc_index. - I think that this is an argument for having more ways to set it.

The full discussion on netfilter-devel is available here:
http://www.spinics.net/lists/netfilter-devel/msg39746.html

I didn't get any responses on the lartc mailing list.

I would like to know if there is a possibility for this patch to be accepted into the kernel,
and/or suggestions for improvements or alternatives.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] Add tcindex to conntrack and add netfilter target/matches
  2015-12-16  0:20 Add tcindex to conntrack and add netfilter target/matches Luuk Paulussen
@ 2015-12-16  0:20 ` Luuk Paulussen
  2015-12-17  5:21   ` kbuild test robot
  0 siblings, 1 reply; 5+ messages in thread
From: Luuk Paulussen @ 2015-12-16  0:20 UTC (permalink / raw)
  To: netdev; +Cc: kyeong.yoo, matt.bennett, Luuk Paulussen

This patch implements support for setting/matching the skb->tc_index
field from Xtables, as well as allowing it to be saved/restored using
connection tracking.

This provides 16 extra bits of mark space that can be saved/restored from
the connection (for performance benefits) when the marking is being done
for tc purposes.

Currently the tc_index field can be set by a number of ingress schedulers,
but if these are not being used, then there is no reason why this field
couldn't also be marked from netfilter.

Once the tc_index field has been set, it can be matched with the existing
tcindex filter in the scheduling code.

Benefits:
1. Marking for tc purposes can be done in this field, alleviating space
   restrictions in generic packet mark.
2. Doesn't increase sk_buff size.
3. tc_index can be saved/restored from connection so that if a flow has
   already been classified, it doesn't have to be done again.
4. save/restore can be done with a mark so that separate marking can be
   done for the two directions of the flow.

Reviewed-by: Matt Bennett <matt.bennett@alliedtelesis.co.nz>
Reviewed-by: Kyeong Yoo <kyeong.yoo@alliedtelesis.co.nz>
---
 include/net/netfilter/nf_conntrack.h               |   6 +-
 include/uapi/linux/netfilter/Kbuild                |   4 +
 include/uapi/linux/netfilter/nf_conntrack_common.h |   1 +
 include/uapi/linux/netfilter/nfnetlink_conntrack.h |   1 +
 include/uapi/linux/netfilter/xt_CONNTCINDEX.h      |   6 +
 include/uapi/linux/netfilter/xt_TCINDEX.h          |   6 +
 include/uapi/linux/netfilter/xt_conntcindex.h      |  31 ++++
 include/uapi/linux/netfilter/xt_tcindex.h          |  15 ++
 net/netfilter/Kconfig                              |  29 ++++
 net/netfilter/Makefile                             |   2 +
 net/netfilter/nf_conntrack_netlink.c               |  39 ++++-
 net/netfilter/xt_conntcindex.c                     | 165 +++++++++++++++++++++
 net/netfilter/xt_tcindex.c                         |  84 +++++++++++
 13 files changed, 385 insertions(+), 4 deletions(-)
 create mode 100644 include/uapi/linux/netfilter/xt_CONNTCINDEX.h
 create mode 100644 include/uapi/linux/netfilter/xt_TCINDEX.h
 create mode 100644 include/uapi/linux/netfilter/xt_conntcindex.h
 create mode 100644 include/uapi/linux/netfilter/xt_tcindex.h
 create mode 100644 net/netfilter/xt_conntcindex.c
 create mode 100644 net/netfilter/xt_tcindex.c

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index fde4068..9b0ab48 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -105,7 +105,11 @@ struct nf_conn {
 
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	u_int32_t mark;
-#endif
+
+#ifdef CONFIG_NET_SCHED
+	u_int16_t tc_index;
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	u_int32_t secmark;
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
index 1d973d2..fedaaab 100644
--- a/include/uapi/linux/netfilter/Kbuild
+++ b/include/uapi/linux/netfilter/Kbuild
@@ -22,6 +22,7 @@ header-y += xt_CHECKSUM.h
 header-y += xt_CLASSIFY.h
 header-y += xt_CONNMARK.h
 header-y += xt_CONNSECMARK.h
+header-y += xt_CONNTCINDEX.h
 header-y += xt_CT.h
 header-y += xt_DSCP.h
 header-y += xt_HMARK.h
@@ -33,6 +34,7 @@ header-y += xt_NFLOG.h
 header-y += xt_NFQUEUE.h
 header-y += xt_RATEEST.h
 header-y += xt_SECMARK.h
+header-y += xt_TCINDEX.h
 header-y += xt_TCPMSS.h
 header-y += xt_TCPOPTSTRIP.h
 header-y += xt_TEE.h
@@ -46,6 +48,7 @@ header-y += xt_connbytes.h
 header-y += xt_connlabel.h
 header-y += xt_connlimit.h
 header-y += xt_connmark.h
+header-y += xt_conntcindex.h
 header-y += xt_conntrack.h
 header-y += xt_cpu.h
 header-y += xt_dccp.h
@@ -81,6 +84,7 @@ header-y += xt_socket.h
 header-y += xt_state.h
 header-y += xt_statistic.h
 header-y += xt_string.h
+header-y += xt_tcindex.h
 header-y += xt_tcpmss.h
 header-y += xt_tcpudp.h
 header-y += xt_time.h
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 319f471..b211bb8 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -107,6 +107,7 @@ enum ip_conntrack_events {
 	IPCT_NATSEQADJ = IPCT_SEQADJ,
 	IPCT_SECMARK,		/* new security mark has been set */
 	IPCT_LABEL,		/* new connlabel has been set */
+	IPCT_TCINDEX,		/* new tc_index has been set */
 };
 
 enum ip_conntrack_expect_events {
diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
index c1a4e144..cfdd15f 100644
--- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -53,6 +53,7 @@ enum ctattr_type {
 	CTA_MARK_MASK,
 	CTA_LABELS,
 	CTA_LABELS_MASK,
+	CTA_TC_INDEX,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
diff --git a/include/uapi/linux/netfilter/xt_CONNTCINDEX.h b/include/uapi/linux/netfilter/xt_CONNTCINDEX.h
new file mode 100644
index 0000000..96eccf3
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_CONNTCINDEX.h
@@ -0,0 +1,6 @@
+#ifndef _XT_CONNTCINDEX_H_target
+#define _XT_CONNTCINDEX_H_target
+
+#include <linux/netfilter/xt_conntcindex.h>
+
+#endif /*_XT_CONNTCINDEX_H_target*/
diff --git a/include/uapi/linux/netfilter/xt_TCINDEX.h b/include/uapi/linux/netfilter/xt_TCINDEX.h
new file mode 100644
index 0000000..a35af8b
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_TCINDEX.h
@@ -0,0 +1,6 @@
+#ifndef _XT_TCINDEX_H_target
+#define _XT_TCINDEX_H_target
+
+#include <linux/netfilter/xt_tcindex.h>
+
+#endif /*_XT_TCINDEX_H_target */
diff --git a/include/uapi/linux/netfilter/xt_conntcindex.h b/include/uapi/linux/netfilter/xt_conntcindex.h
new file mode 100644
index 0000000..d82329a
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_conntcindex.h
@@ -0,0 +1,31 @@
+#ifndef _XT_CONNTCINDEX_H
+#define _XT_CONNTCINDEX_H
+
+#include <linux/types.h>
+
+/* Copyright (C) 2015 Allied Telesis Labs NZ
+ * by Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+enum {
+	XT_CONNTCINDEX_SET = 0,
+	XT_CONNTCINDEX_SAVE,
+	XT_CONNTCINDEX_RESTORE
+};
+
+struct xt_conntcindex_tginfo1 {
+	__u16 ctmark, ctmask, nfmask;
+	__u8 mode;
+};
+
+struct xt_conntcindex_mtinfo1 {
+	__u16 mark, mask;
+	__u8 invert;
+};
+
+#endif /*_XT_CONNTCINDEX_H*/
diff --git a/include/uapi/linux/netfilter/xt_tcindex.h b/include/uapi/linux/netfilter/xt_tcindex.h
new file mode 100644
index 0000000..cb012fa
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_tcindex.h
@@ -0,0 +1,15 @@
+#ifndef _XT_TCINDEX_H
+#define _XT_TCINDEX_H
+
+#include <linux/types.h>
+
+struct xt_tcindex_tginfo1 {
+	__u16 mark, mask;
+};
+
+struct xt_tcindex_mtinfo1 {
+	__u16 mark, mask;
+	__u8 invert;
+};
+
+#endif /*_XT_TCINDEX_H*/
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 4692782..3bff4dd 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -603,6 +603,35 @@ config NETFILTER_XT_CONNMARK
 	ctmark), similarly to the packet mark (nfmark). Using this
 	target and match, you can set and match on this mark.
 
+config NETFILTER_XT_TCINDEX
+	tristate 'tc_index mark target and match support'
+	depends on NETFILTER_ADVANCED
+	depends on NET_SCHED
+	default n
+	---help---
+	This option adds the "TCINDEX" target and "tcindex" match.
+
+	tcindex matching allows you to match packets based on the "tc_index" value
+	in the packet.
+	The target allows you to create rules in the "mangle" table which alter
+	the tc_index field associated with the packet.
+
+	This is an alternative to setting the tc_index field based on the priority
+	fields of the incoming traffic.  In traffic control, this mark can be matched
+	using the tcindex filter.
+
+config NETFILTER_XT_CONNTCINDEX
+	tristate 'ct tc_index mark target and match support'
+	depends on NF_CONNTRACK_MARK
+	depends on NETFILTER_ADVANCED
+	depends on NET_SCHED
+	default n
+	---help---
+	This option adds the "CONNTCINDEX" target and "conntcindex" match.
+
+	Using this target and match, you can set and match on the tc_index mark in the
+	connection.  This can also be saved/restored to the packet tc_index mark.
+
 config NETFILTER_XT_SET
 	tristate 'set target and match support'
 	depends on IP_SET
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 7638c36..7492ef6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -96,6 +96,8 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 # combos
 obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o
 obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o
+obj-$(CONFIG_NETFILTER_XT_TCINDEX) += xt_tcindex.o
+obj-$(CONFIG_NETFILTER_XT_CONNTCINDEX) += xt_conntcindex.o
 obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o
 obj-$(CONFIG_NETFILTER_XT_NAT) += xt_nat.o
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9f52729..a1db545 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -314,6 +314,21 @@ nla_put_failure:
 #define ctnetlink_dump_mark(a, b) (0)
 #endif
 
+#if defined CONFIG_NET_SCHED && defined CONFIG_NF_CONNTRACK_MARK
+static inline int
+ctnetlink_dump_tcindex(struct sk_buff *skb, const struct nf_conn *ct)
+{
+	if (nla_put_be16(skb, CTA_TC_INDEX, htonl(ct->tc_index)))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+#else
+#define ctnetlink_dump_tcindex(a, b) (0)
+#endif
+
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 static inline int
 ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
@@ -521,6 +536,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
 	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_mark(skb, ct) < 0 ||
+	    ctnetlink_dump_tcindex(skb, ct) < 0 ||
 	    ctnetlink_dump_secctx(skb, ct) < 0 ||
 	    ctnetlink_dump_labels(skb, ct) < 0 ||
 	    ctnetlink_dump_id(skb, ct) < 0 ||
@@ -749,7 +765,13 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
 	if ((events & (1 << IPCT_MARK) || ct->mark)
 	    && ctnetlink_dump_mark(skb, ct) < 0)
 		goto nla_put_failure;
-#endif
+
+#ifdef CONFIG_NET_SCHED
+	if ((events & (1 << IPCT_TCINDEX) || ct->tc_index)
+	    && ctnetlink_dump_tcindex(skb, ct) < 0)
+		goto nla_put_failure;
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 	rcu_read_unlock();
 
 	nlmsg_end(skb, nlh);
@@ -1092,6 +1114,7 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
 				    .len = NF_CT_LABELS_MAX_SIZE },
 	[CTA_LABELS_MASK]	= { .type = NLA_BINARY,
 				    .len = NF_CT_LABELS_MAX_SIZE },
+	[CTA_TC_INDEX]		= { .type = NLA_U16 },
 };
 
 static int ctnetlink_flush_conntrack(struct net *net,
@@ -1697,7 +1720,13 @@ ctnetlink_change_conntrack(struct nf_conn *ct,
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
-#endif
+#ifdef CONFIG_NET_SCHED
+	if (cda[CTA_TC_INDEX])
+		ct->tc_index = ntohs(nla_get_be16(cda[CTA_TC_INDEX]));
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
+
 
 	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
 		err = ctnetlink_change_seq_adj(ct, cda);
@@ -1824,7 +1853,11 @@ ctnetlink_create_conntrack(struct net *net,
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
-#endif
+#ifdef CONFIG_NET_SCHED
+	if (cda[CTA_TC_INDEX])
+		ct->tc_index = ntohs(nla_get_be16(cda[CTA_TC_INDEX]));
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 
 	/* setup master conntrack: this is a confirmed expectation */
 	if (cda[CTA_TUPLE_MASTER]) {
diff --git a/net/netfilter/xt_conntcindex.c b/net/netfilter/xt_conntcindex.c
new file mode 100644
index 0000000..838dacf
--- /dev/null
+++ b/net/netfilter/xt_conntcindex.c
@@ -0,0 +1,165 @@
+/*
+ *	xt_conntcindex - Netfilter module to operate on connection tc_index marks
+ *
+ *	Copyright (C) 2015 Allied Telesis Labs NZ
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Heavily based on xt_connmark.c
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_conntcindex.h>
+
+MODULE_AUTHOR("Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>");
+MODULE_DESCRIPTION("Xtables: connection tc_index mark operations");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_CONNTCINDEX");
+MODULE_ALIAS("ip6t_CONNTCINDEX");
+MODULE_ALIAS("ipt_conntcindex");
+MODULE_ALIAS("ip6t_conntcindex");
+
+static unsigned int
+conntcindex_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_conntcindex_tginfo1 *info = par->targinfo;
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct;
+	u_int32_t newmark;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (ct == NULL)
+		return XT_CONTINUE;
+
+	switch (info->mode) {
+	case XT_CONNTCINDEX_SET:
+		newmark = (ct->tc_index & ~info->ctmask) ^ info->ctmark;
+		if (ct->tc_index != newmark) {
+			ct->tc_index = newmark;
+			nf_conntrack_event_cache(IPCT_TCINDEX, ct);
+		}
+		break;
+	case XT_CONNTCINDEX_SAVE:
+		newmark = (ct->tc_index & ~info->ctmask) ^
+		          (skb->tc_index & info->nfmask);
+		if (ct->tc_index != newmark) {
+			ct->tc_index = newmark;
+			nf_conntrack_event_cache(IPCT_TCINDEX, ct);
+		}
+		break;
+	case XT_CONNTCINDEX_RESTORE:
+		newmark = (skb->tc_index & ~info->nfmask) ^
+		          (ct->tc_index & info->ctmask);
+		skb->tc_index = newmark;
+		break;
+	}
+
+	return XT_CONTINUE;
+}
+
+static int conntcindex_tg_check(const struct xt_tgchk_param *par)
+{
+	int ret;
+
+	ret = nf_ct_l3proto_try_module_get(par->family);
+	if (ret < 0)
+		pr_info("cannot load conntrack support for proto=%u\n",
+			par->family);
+	return ret;
+}
+
+static void conntcindex_tg_destroy(const struct xt_tgdtor_param *par)
+{
+	nf_ct_l3proto_module_put(par->family);
+}
+
+static bool
+conntcindex_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_conntcindex_mtinfo1 *info = par->matchinfo;
+	enum ip_conntrack_info ctinfo;
+	const struct nf_conn *ct;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (ct == NULL)
+		return false;
+
+	return ((ct->tc_index & info->mask) == info->mark) ^ info->invert;
+}
+
+static int conntcindex_mt_check(const struct xt_mtchk_param *par)
+{
+	int ret;
+
+	ret = nf_ct_l3proto_try_module_get(par->family);
+	if (ret < 0)
+		pr_info("cannot load conntrack support for proto=%u\n",
+			par->family);
+	return ret;
+}
+
+static void conntcindex_mt_destroy(const struct xt_mtdtor_param *par)
+{
+	nf_ct_l3proto_module_put(par->family);
+}
+
+static struct xt_target conntcindex_tg_reg __read_mostly = {
+	.name           = "CONNTCINDEX",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.checkentry     = conntcindex_tg_check,
+	.target         = conntcindex_tg,
+	.targetsize     = sizeof(struct xt_conntcindex_tginfo1),
+	.destroy        = conntcindex_tg_destroy,
+	.me             = THIS_MODULE,
+};
+
+static struct xt_match conntcindex_mt_reg __read_mostly = {
+	.name           = "conntcindex",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.checkentry     = conntcindex_mt_check,
+	.match          = conntcindex_mt,
+	.matchsize      = sizeof(struct xt_conntcindex_mtinfo1),
+	.destroy        = conntcindex_mt_destroy,
+	.me             = THIS_MODULE,
+};
+
+static int __init conntcindex_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_target(&conntcindex_tg_reg);
+	if (ret < 0)
+		return ret;
+	ret = xt_register_match(&conntcindex_mt_reg);
+	if (ret < 0) {
+		xt_unregister_target(&conntcindex_tg_reg);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit conntcindex_mt_exit(void)
+{
+	xt_unregister_match(&conntcindex_mt_reg);
+	xt_unregister_target(&conntcindex_tg_reg);
+}
+
+module_init(conntcindex_mt_init);
+module_exit(conntcindex_mt_exit);
diff --git a/net/netfilter/xt_tcindex.c b/net/netfilter/xt_tcindex.c
new file mode 100644
index 0000000..7de29cd
--- /dev/null
+++ b/net/netfilter/xt_tcindex.c
@@ -0,0 +1,84 @@
+/*
+ *	xt_tcindex - Netfilter module to match/tag on tc_index mark value
+ *
+ *	(C) 2015 Allied Telesis Labs NZ.
+  *
+ *	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.
+ *
+ *	Heavily based on xt_mark.c
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/xt_tcindex.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>");
+MODULE_DESCRIPTION("Xtables: packet tc_index mark operations");
+MODULE_ALIAS("ipt_tcindex");
+MODULE_ALIAS("ip6t_tcindex");
+MODULE_ALIAS("ipt_TCINDEX");
+MODULE_ALIAS("ip6t_TCINDEX");
+
+static unsigned int
+tcindex_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tcindex_tginfo1 *info = par->targinfo;
+
+	skb->tc_index = (skb->tc_index & ~info->mask) ^ info->mark;
+	return XT_CONTINUE;
+}
+
+static bool
+tcindex_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_tcindex_mtinfo1 *info = par->matchinfo;
+
+	return ((skb->tc_index & info->mask) == info->mark) ^ info->invert;
+}
+
+static struct xt_target tcindex_tg_reg __read_mostly = {
+	.name           = "TCINDEX",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.target         = tcindex_tg,
+	.targetsize     = sizeof(struct xt_tcindex_tginfo1),
+	.me             = THIS_MODULE,
+};
+
+static struct xt_match tcindex_mt_reg __read_mostly = {
+	.name           = "tcindex",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.match          = tcindex_mt,
+	.matchsize      = sizeof(struct xt_tcindex_mtinfo1),
+	.me             = THIS_MODULE,
+};
+
+static int __init tcindex_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_target(&tcindex_tg_reg);
+	if (ret < 0)
+		return ret;
+	ret = xt_register_match(&tcindex_mt_reg);
+	if (ret < 0) {
+		xt_unregister_target(&tcindex_tg_reg);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit tcindex_mt_exit(void)
+{
+	xt_unregister_match(&tcindex_mt_reg);
+	xt_unregister_target(&tcindex_tg_reg);
+}
+
+module_init(tcindex_mt_init);
+module_exit(tcindex_mt_exit);
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add tcindex to conntrack and add netfilter target/matches
  2015-12-16  0:20 ` [PATCH] " Luuk Paulussen
@ 2015-12-17  5:21   ` kbuild test robot
  2015-12-21 22:34     ` [PATCH v2] net-next: " Luuk Paulussen
  0 siblings, 1 reply; 5+ messages in thread
From: kbuild test robot @ 2015-12-17  5:21 UTC (permalink / raw)
  To: Luuk Paulussen
  Cc: kbuild-all, netdev, kyeong.yoo, matt.bennett, Luuk Paulussen

[-- Attachment #1: Type: text/plain, Size: 1254 bytes --]

Hi Luuk,

[auto build test ERROR on nf-next/master]
[also build test ERROR on v4.4-rc5 next-20151216]

url:    https://github.com/0day-ci/linux/commits/Luuk-Paulussen/Add-tcindex-to-conntrack-and-add-netfilter-target-matches/20151216-082324
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next master
config: x86_64-randconfig-x019-12171138 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   net/built-in.o: In function `conntcindex_tg_destroy':
>> xt_conntcindex.c:(.text+0x7cf5d): undefined reference to `nf_ct_l3proto_module_put'
   net/built-in.o: In function `conntcindex_mt_destroy':
   xt_conntcindex.c:(.text+0x7cf71): undefined reference to `nf_ct_l3proto_module_put'
   net/built-in.o: In function `conntcindex_tg_check':
>> xt_conntcindex.c:(.text+0x7d0aa): undefined reference to `nf_ct_l3proto_try_module_get'
   net/built-in.o: In function `conntcindex_mt_check':
   xt_conntcindex.c:(.text+0x7d0f2): undefined reference to `nf_ct_l3proto_try_module_get'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 25409 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2] net-next: Add tcindex to conntrack and add netfilter target/matches
  2015-12-17  5:21   ` kbuild test robot
@ 2015-12-21 22:34     ` Luuk Paulussen
  0 siblings, 0 replies; 5+ messages in thread
From: Luuk Paulussen @ 2015-12-21 22:34 UTC (permalink / raw)
  To: netdev; +Cc: davem, kyeong.yoo, matt.bennett, Luuk Paulussen

This patch implements support for setting/matching the skb->tc_index
field from Xtables, as well as allowing it to be saved/restored using
connection tracking.

This provides 16 extra bits of mark space that can be saved/restored from
the connection (for performance benefits) when the marking is being done
for tc purposes.

Currently the tc_index field can be set by a number of ingress schedulers,
but if these are not being used, then there is no reason why this field
couldn't also be marked from netfilter.

Once the tc_index field has been set, it can be matched with the existing
tcindex filter in the scheduling code.

Benefits:
1. Marking for tc purposes can be done in this field, alleviating space
   restrictions in generic packet mark.
2. Doesn't increase sk_buff size.
3. tc_index can be saved/restored from connection so that if a flow has
   already been classified, it doesn't have to be done again.
4. save/restore can be done with a mark so that separate marking can be
   done for the two directions of the flow.

Reviewed-by: Matt Bennett <matt.bennett@alliedtelesis.co.nz>
Reviewed-by: Kyeong Yoo <kyeong.yoo@alliedtelesis.co.nz>
Signed-off-by: Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>
---
 include/net/netfilter/nf_conntrack.h               |   6 +-
 include/uapi/linux/netfilter/Kbuild                |   4 +
 include/uapi/linux/netfilter/nf_conntrack_common.h |   1 +
 include/uapi/linux/netfilter/nfnetlink_conntrack.h |   1 +
 include/uapi/linux/netfilter/xt_CONNTCINDEX.h      |   6 +
 include/uapi/linux/netfilter/xt_TCINDEX.h          |   6 +
 include/uapi/linux/netfilter/xt_conntcindex.h      |  31 ++++
 include/uapi/linux/netfilter/xt_tcindex.h          |  15 ++
 net/netfilter/Kconfig                              |  30 ++++
 net/netfilter/Makefile                             |   2 +
 net/netfilter/nf_conntrack_netlink.c               |  38 ++++-
 net/netfilter/xt_conntcindex.c                     | 165 +++++++++++++++++++++
 net/netfilter/xt_tcindex.c                         |  84 +++++++++++
 13 files changed, 385 insertions(+), 4 deletions(-)
 create mode 100644 include/uapi/linux/netfilter/xt_CONNTCINDEX.h
 create mode 100644 include/uapi/linux/netfilter/xt_TCINDEX.h
 create mode 100644 include/uapi/linux/netfilter/xt_conntcindex.h
 create mode 100644 include/uapi/linux/netfilter/xt_tcindex.h
 create mode 100644 net/netfilter/xt_conntcindex.c
 create mode 100644 net/netfilter/xt_tcindex.c

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index fde4068..9b0ab48 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -105,7 +105,11 @@ struct nf_conn {
 
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	u_int32_t mark;
-#endif
+
+#ifdef CONFIG_NET_SCHED
+	u_int16_t tc_index;
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	u_int32_t secmark;
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
index 1d973d2..fedaaab 100644
--- a/include/uapi/linux/netfilter/Kbuild
+++ b/include/uapi/linux/netfilter/Kbuild
@@ -22,6 +22,7 @@ header-y += xt_CHECKSUM.h
 header-y += xt_CLASSIFY.h
 header-y += xt_CONNMARK.h
 header-y += xt_CONNSECMARK.h
+header-y += xt_CONNTCINDEX.h
 header-y += xt_CT.h
 header-y += xt_DSCP.h
 header-y += xt_HMARK.h
@@ -33,6 +34,7 @@ header-y += xt_NFLOG.h
 header-y += xt_NFQUEUE.h
 header-y += xt_RATEEST.h
 header-y += xt_SECMARK.h
+header-y += xt_TCINDEX.h
 header-y += xt_TCPMSS.h
 header-y += xt_TCPOPTSTRIP.h
 header-y += xt_TEE.h
@@ -46,6 +48,7 @@ header-y += xt_connbytes.h
 header-y += xt_connlabel.h
 header-y += xt_connlimit.h
 header-y += xt_connmark.h
+header-y += xt_conntcindex.h
 header-y += xt_conntrack.h
 header-y += xt_cpu.h
 header-y += xt_dccp.h
@@ -81,6 +84,7 @@ header-y += xt_socket.h
 header-y += xt_state.h
 header-y += xt_statistic.h
 header-y += xt_string.h
+header-y += xt_tcindex.h
 header-y += xt_tcpmss.h
 header-y += xt_tcpudp.h
 header-y += xt_time.h
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 319f471..b211bb8 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -107,6 +107,7 @@ enum ip_conntrack_events {
 	IPCT_NATSEQADJ = IPCT_SEQADJ,
 	IPCT_SECMARK,		/* new security mark has been set */
 	IPCT_LABEL,		/* new connlabel has been set */
+	IPCT_TCINDEX,		/* new tc_index has been set */
 };
 
 enum ip_conntrack_expect_events {
diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
index c1a4e144..cfdd15f 100644
--- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -53,6 +53,7 @@ enum ctattr_type {
 	CTA_MARK_MASK,
 	CTA_LABELS,
 	CTA_LABELS_MASK,
+	CTA_TC_INDEX,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
diff --git a/include/uapi/linux/netfilter/xt_CONNTCINDEX.h b/include/uapi/linux/netfilter/xt_CONNTCINDEX.h
new file mode 100644
index 0000000..96eccf3
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_CONNTCINDEX.h
@@ -0,0 +1,6 @@
+#ifndef _XT_CONNTCINDEX_H_target
+#define _XT_CONNTCINDEX_H_target
+
+#include <linux/netfilter/xt_conntcindex.h>
+
+#endif /*_XT_CONNTCINDEX_H_target*/
diff --git a/include/uapi/linux/netfilter/xt_TCINDEX.h b/include/uapi/linux/netfilter/xt_TCINDEX.h
new file mode 100644
index 0000000..a35af8b
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_TCINDEX.h
@@ -0,0 +1,6 @@
+#ifndef _XT_TCINDEX_H_target
+#define _XT_TCINDEX_H_target
+
+#include <linux/netfilter/xt_tcindex.h>
+
+#endif /*_XT_TCINDEX_H_target */
diff --git a/include/uapi/linux/netfilter/xt_conntcindex.h b/include/uapi/linux/netfilter/xt_conntcindex.h
new file mode 100644
index 0000000..d82329a
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_conntcindex.h
@@ -0,0 +1,31 @@
+#ifndef _XT_CONNTCINDEX_H
+#define _XT_CONNTCINDEX_H
+
+#include <linux/types.h>
+
+/* Copyright (C) 2015 Allied Telesis Labs NZ
+ * by Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+enum {
+	XT_CONNTCINDEX_SET = 0,
+	XT_CONNTCINDEX_SAVE,
+	XT_CONNTCINDEX_RESTORE
+};
+
+struct xt_conntcindex_tginfo1 {
+	__u16 ctmark, ctmask, nfmask;
+	__u8 mode;
+};
+
+struct xt_conntcindex_mtinfo1 {
+	__u16 mark, mask;
+	__u8 invert;
+};
+
+#endif /*_XT_CONNTCINDEX_H*/
diff --git a/include/uapi/linux/netfilter/xt_tcindex.h b/include/uapi/linux/netfilter/xt_tcindex.h
new file mode 100644
index 0000000..cb012fa
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_tcindex.h
@@ -0,0 +1,15 @@
+#ifndef _XT_TCINDEX_H
+#define _XT_TCINDEX_H
+
+#include <linux/types.h>
+
+struct xt_tcindex_tginfo1 {
+	__u16 mark, mask;
+};
+
+struct xt_tcindex_mtinfo1 {
+	__u16 mark, mask;
+	__u8 invert;
+};
+
+#endif /*_XT_TCINDEX_H*/
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 4692782..8623157 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -603,6 +603,36 @@ config NETFILTER_XT_CONNMARK
 	ctmark), similarly to the packet mark (nfmark). Using this
 	target and match, you can set and match on this mark.
 
+config NETFILTER_XT_TCINDEX
+	tristate 'tc_index mark target and match support'
+	depends on NETFILTER_ADVANCED
+	depends on NET_SCHED
+	default n
+	---help---
+	This option adds the "TCINDEX" target and "tcindex" match.
+
+	tcindex matching allows you to match packets based on the "tc_index" value
+	in the packet.
+	The target allows you to create rules in the "mangle" table which alter
+	the tc_index field associated with the packet.
+
+	This is an alternative to setting the tc_index field based on the priority
+	fields of the incoming traffic.  In traffic control, this mark can be matched
+	using the tcindex filter.
+
+config NETFILTER_XT_CONNTCINDEX
+	tristate 'ct tc_index mark target and match support'
+	depends on NF_CONNTRACK
+	depends on NF_CONNTRACK_MARK
+	depends on NETFILTER_ADVANCED
+	depends on NET_SCHED
+	default n
+	---help---
+	This option adds the "CONNTCINDEX" target and "conntcindex" match.
+
+	Using this target and match, you can set and match on the tc_index mark in the
+	connection.  This can also be saved/restored to the packet tc_index mark.
+
 config NETFILTER_XT_SET
 	tristate 'set target and match support'
 	depends on IP_SET
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 2293484..d648ae0 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -96,6 +96,8 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 # combos
 obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o
 obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o
+obj-$(CONFIG_NETFILTER_XT_TCINDEX) += xt_tcindex.o
+obj-$(CONFIG_NETFILTER_XT_CONNTCINDEX) += xt_conntcindex.o
 obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o
 obj-$(CONFIG_NETFILTER_XT_NAT) += xt_nat.o
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9f52729..e33a765 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -314,6 +314,21 @@ nla_put_failure:
 #define ctnetlink_dump_mark(a, b) (0)
 #endif
 
+#if defined CONFIG_NET_SCHED && defined CONFIG_NF_CONNTRACK_MARK
+static inline int
+ctnetlink_dump_tcindex(struct sk_buff *skb, const struct nf_conn *ct)
+{
+	if (nla_put_be16(skb, CTA_TC_INDEX, htonl(ct->tc_index)))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+#else
+#define ctnetlink_dump_tcindex(a, b) (0)
+#endif
+
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 static inline int
 ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
@@ -521,6 +536,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
 	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_mark(skb, ct) < 0 ||
+	    ctnetlink_dump_tcindex(skb, ct) < 0 ||
 	    ctnetlink_dump_secctx(skb, ct) < 0 ||
 	    ctnetlink_dump_labels(skb, ct) < 0 ||
 	    ctnetlink_dump_id(skb, ct) < 0 ||
@@ -749,7 +765,13 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
 	if ((events & (1 << IPCT_MARK) || ct->mark)
 	    && ctnetlink_dump_mark(skb, ct) < 0)
 		goto nla_put_failure;
-#endif
+
+#ifdef CONFIG_NET_SCHED
+	if ((events & (1 << IPCT_TCINDEX) || ct->tc_index) &&
+	    ctnetlink_dump_tcindex(skb, ct) < 0)
+		goto nla_put_failure;
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 	rcu_read_unlock();
 
 	nlmsg_end(skb, nlh);
@@ -1092,6 +1114,7 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
 				    .len = NF_CT_LABELS_MAX_SIZE },
 	[CTA_LABELS_MASK]	= { .type = NLA_BINARY,
 				    .len = NF_CT_LABELS_MAX_SIZE },
+	[CTA_TC_INDEX]		= { .type = NLA_U16 },
 };
 
 static int ctnetlink_flush_conntrack(struct net *net,
@@ -1697,7 +1720,12 @@ ctnetlink_change_conntrack(struct nf_conn *ct,
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
-#endif
+#ifdef CONFIG_NET_SCHED
+	if (cda[CTA_TC_INDEX])
+		ct->tc_index = ntohs(nla_get_be16(cda[CTA_TC_INDEX]));
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
 
 	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
 		err = ctnetlink_change_seq_adj(ct, cda);
@@ -1824,7 +1852,11 @@ ctnetlink_create_conntrack(struct net *net,
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
-#endif
+#ifdef CONFIG_NET_SCHED
+	if (cda[CTA_TC_INDEX])
+		ct->tc_index = ntohs(nla_get_be16(cda[CTA_TC_INDEX]));
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 
 	/* setup master conntrack: this is a confirmed expectation */
 	if (cda[CTA_TUPLE_MASTER]) {
diff --git a/net/netfilter/xt_conntcindex.c b/net/netfilter/xt_conntcindex.c
new file mode 100644
index 0000000..1b37562
--- /dev/null
+++ b/net/netfilter/xt_conntcindex.c
@@ -0,0 +1,165 @@
+/*
+ * xt_conntcindex - Netfilter module to operate on connection tc_index marks
+ *
+ * Copyright (C) 2015 Allied Telesis Labs NZ
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Heavily based on xt_connmark.c
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_conntcindex.h>
+
+MODULE_AUTHOR("Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>");
+MODULE_DESCRIPTION("Xtables: connection tc_index mark operations");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_CONNTCINDEX");
+MODULE_ALIAS("ip6t_CONNTCINDEX");
+MODULE_ALIAS("ipt_conntcindex");
+MODULE_ALIAS("ip6t_conntcindex");
+
+static unsigned int
+conntcindex_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_conntcindex_tginfo1 *info = par->targinfo;
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct;
+	u32 newmark;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct)
+		return XT_CONTINUE;
+
+	switch (info->mode) {
+	case XT_CONNTCINDEX_SET:
+		newmark = (ct->tc_index & ~info->ctmask) ^ info->ctmark;
+		if (ct->tc_index != newmark) {
+			ct->tc_index = newmark;
+			nf_conntrack_event_cache(IPCT_TCINDEX, ct);
+		}
+		break;
+	case XT_CONNTCINDEX_SAVE:
+		newmark = (ct->tc_index & ~info->ctmask) ^
+			  (skb->tc_index & info->nfmask);
+		if (ct->tc_index != newmark) {
+			ct->tc_index = newmark;
+			nf_conntrack_event_cache(IPCT_TCINDEX, ct);
+		}
+		break;
+	case XT_CONNTCINDEX_RESTORE:
+		newmark = (skb->tc_index & ~info->nfmask) ^
+			  (ct->tc_index & info->ctmask);
+		skb->tc_index = newmark;
+		break;
+	}
+
+	return XT_CONTINUE;
+}
+
+static int conntcindex_tg_check(const struct xt_tgchk_param *par)
+{
+	int ret;
+
+	ret = nf_ct_l3proto_try_module_get(par->family);
+	if (ret < 0)
+		pr_info("cannot load conntrack support for proto=%u\n",
+			par->family);
+	return ret;
+}
+
+static void conntcindex_tg_destroy(const struct xt_tgdtor_param *par)
+{
+	nf_ct_l3proto_module_put(par->family);
+}
+
+static bool
+conntcindex_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_conntcindex_mtinfo1 *info = par->matchinfo;
+	enum ip_conntrack_info ctinfo;
+	const struct nf_conn *ct;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct)
+		return false;
+
+	return ((ct->tc_index & info->mask) == info->mark) ^ info->invert;
+}
+
+static int conntcindex_mt_check(const struct xt_mtchk_param *par)
+{
+	int ret;
+
+	ret = nf_ct_l3proto_try_module_get(par->family);
+	if (ret < 0)
+		pr_info("cannot load conntrack support for proto=%u\n",
+			par->family);
+	return ret;
+}
+
+static void conntcindex_mt_destroy(const struct xt_mtdtor_param *par)
+{
+	nf_ct_l3proto_module_put(par->family);
+}
+
+static struct xt_target conntcindex_tg_reg __read_mostly = {
+	.name           = "CONNTCINDEX",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.checkentry     = conntcindex_tg_check,
+	.target         = conntcindex_tg,
+	.targetsize     = sizeof(struct xt_conntcindex_tginfo1),
+	.destroy        = conntcindex_tg_destroy,
+	.me             = THIS_MODULE,
+};
+
+static struct xt_match conntcindex_mt_reg __read_mostly = {
+	.name           = "conntcindex",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.checkentry     = conntcindex_mt_check,
+	.match          = conntcindex_mt,
+	.matchsize      = sizeof(struct xt_conntcindex_mtinfo1),
+	.destroy        = conntcindex_mt_destroy,
+	.me             = THIS_MODULE,
+};
+
+static int __init conntcindex_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_target(&conntcindex_tg_reg);
+	if (ret < 0)
+		return ret;
+	ret = xt_register_match(&conntcindex_mt_reg);
+	if (ret < 0) {
+		xt_unregister_target(&conntcindex_tg_reg);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit conntcindex_mt_exit(void)
+{
+	xt_unregister_match(&conntcindex_mt_reg);
+	xt_unregister_target(&conntcindex_tg_reg);
+}
+
+module_init(conntcindex_mt_init);
+module_exit(conntcindex_mt_exit);
diff --git a/net/netfilter/xt_tcindex.c b/net/netfilter/xt_tcindex.c
new file mode 100644
index 0000000..7de29cd
--- /dev/null
+++ b/net/netfilter/xt_tcindex.c
@@ -0,0 +1,84 @@
+/*
+ *	xt_tcindex - Netfilter module to match/tag on tc_index mark value
+ *
+ *	(C) 2015 Allied Telesis Labs NZ.
+  *
+ *	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.
+ *
+ *	Heavily based on xt_mark.c
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/xt_tcindex.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>");
+MODULE_DESCRIPTION("Xtables: packet tc_index mark operations");
+MODULE_ALIAS("ipt_tcindex");
+MODULE_ALIAS("ip6t_tcindex");
+MODULE_ALIAS("ipt_TCINDEX");
+MODULE_ALIAS("ip6t_TCINDEX");
+
+static unsigned int
+tcindex_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tcindex_tginfo1 *info = par->targinfo;
+
+	skb->tc_index = (skb->tc_index & ~info->mask) ^ info->mark;
+	return XT_CONTINUE;
+}
+
+static bool
+tcindex_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_tcindex_mtinfo1 *info = par->matchinfo;
+
+	return ((skb->tc_index & info->mask) == info->mark) ^ info->invert;
+}
+
+static struct xt_target tcindex_tg_reg __read_mostly = {
+	.name           = "TCINDEX",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.target         = tcindex_tg,
+	.targetsize     = sizeof(struct xt_tcindex_tginfo1),
+	.me             = THIS_MODULE,
+};
+
+static struct xt_match tcindex_mt_reg __read_mostly = {
+	.name           = "tcindex",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.match          = tcindex_mt,
+	.matchsize      = sizeof(struct xt_tcindex_mtinfo1),
+	.me             = THIS_MODULE,
+};
+
+static int __init tcindex_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_target(&tcindex_tg_reg);
+	if (ret < 0)
+		return ret;
+	ret = xt_register_match(&tcindex_mt_reg);
+	if (ret < 0) {
+		xt_unregister_target(&tcindex_tg_reg);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit tcindex_mt_exit(void)
+{
+	xt_unregister_match(&tcindex_mt_reg);
+	xt_unregister_target(&tcindex_tg_reg);
+}
+
+module_init(tcindex_mt_init);
+module_exit(tcindex_mt_exit);
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2] net-next: Add tcindex to conntrack and add netfilter target/matches
       [not found] ` <1450821040-18837-1-git-send-email-luuk.paulussen-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
@ 2015-12-22 21:50   ` Luuk Paulussen
  0 siblings, 0 replies; 5+ messages in thread
From: Luuk Paulussen @ 2015-12-22 21:50 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: Pablo Neira Ayuso, Patrick McHardy, Jozsef Kadlecsik,
	David Miller, netfilter-devel-u79uwXL29TY76Z2rM5mHXA,
	coreteam-Cap9r6Oaw4JrovVCs/uTlw,
	linux-api-u79uwXL29TY76Z2rM5mHXA, Luuk Paulussen

This patch implements support for setting/matching the skb->tc_index
field from Xtables, as well as allowing it to be saved/restored using
connection tracking.

This provides 16 extra bits of mark space that can be saved/restored from
the connection (for performance benefits) when the marking is being done
for tc purposes.

Currently the tc_index field can be set by a number of ingress schedulers,
but if these are not being used, then there is no reason why this field
couldn't also be marked from netfilter.

Once the tc_index field has been set, it can be matched with the existing
tcindex filter in the scheduling code.

Benefits:
1. Marking for tc purposes can be done in this field, alleviating space
   restrictions in generic packet mark.
2. Doesn't increase sk_buff size.
3. tc_index can be saved/restored from connection so that if a flow has
   already been classified, it doesn't have to be done again.
4. save/restore can be done with a mark so that separate marking can be
   done for the two directions of the flow.

Reviewed-by: Matt Bennett <matt.bennett-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
Reviewed-by: Kyeong Yoo <kyeong.yoo-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
Signed-off-by: Luuk Paulussen <luuk.paulussen-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
---
 include/net/netfilter/nf_conntrack.h               |   6 +-
 include/uapi/linux/netfilter/Kbuild                |   4 +
 include/uapi/linux/netfilter/nf_conntrack_common.h |   1 +
 include/uapi/linux/netfilter/nfnetlink_conntrack.h |   1 +
 include/uapi/linux/netfilter/xt_CONNTCINDEX.h      |   6 +
 include/uapi/linux/netfilter/xt_TCINDEX.h          |   6 +
 include/uapi/linux/netfilter/xt_conntcindex.h      |  31 ++++
 include/uapi/linux/netfilter/xt_tcindex.h          |  15 ++
 net/netfilter/Kconfig                              |  30 ++++
 net/netfilter/Makefile                             |   2 +
 net/netfilter/nf_conntrack_netlink.c               |  38 ++++-
 net/netfilter/xt_conntcindex.c                     | 165 +++++++++++++++++++++
 net/netfilter/xt_tcindex.c                         |  84 +++++++++++
 13 files changed, 385 insertions(+), 4 deletions(-)
 create mode 100644 include/uapi/linux/netfilter/xt_CONNTCINDEX.h
 create mode 100644 include/uapi/linux/netfilter/xt_TCINDEX.h
 create mode 100644 include/uapi/linux/netfilter/xt_conntcindex.h
 create mode 100644 include/uapi/linux/netfilter/xt_tcindex.h
 create mode 100644 net/netfilter/xt_conntcindex.c
 create mode 100644 net/netfilter/xt_tcindex.c

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index fde4068..9b0ab48 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -105,7 +105,11 @@ struct nf_conn {
 
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	u_int32_t mark;
-#endif
+
+#ifdef CONFIG_NET_SCHED
+	u_int16_t tc_index;
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 	u_int32_t secmark;
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
index 1d973d2..fedaaab 100644
--- a/include/uapi/linux/netfilter/Kbuild
+++ b/include/uapi/linux/netfilter/Kbuild
@@ -22,6 +22,7 @@ header-y += xt_CHECKSUM.h
 header-y += xt_CLASSIFY.h
 header-y += xt_CONNMARK.h
 header-y += xt_CONNSECMARK.h
+header-y += xt_CONNTCINDEX.h
 header-y += xt_CT.h
 header-y += xt_DSCP.h
 header-y += xt_HMARK.h
@@ -33,6 +34,7 @@ header-y += xt_NFLOG.h
 header-y += xt_NFQUEUE.h
 header-y += xt_RATEEST.h
 header-y += xt_SECMARK.h
+header-y += xt_TCINDEX.h
 header-y += xt_TCPMSS.h
 header-y += xt_TCPOPTSTRIP.h
 header-y += xt_TEE.h
@@ -46,6 +48,7 @@ header-y += xt_connbytes.h
 header-y += xt_connlabel.h
 header-y += xt_connlimit.h
 header-y += xt_connmark.h
+header-y += xt_conntcindex.h
 header-y += xt_conntrack.h
 header-y += xt_cpu.h
 header-y += xt_dccp.h
@@ -81,6 +84,7 @@ header-y += xt_socket.h
 header-y += xt_state.h
 header-y += xt_statistic.h
 header-y += xt_string.h
+header-y += xt_tcindex.h
 header-y += xt_tcpmss.h
 header-y += xt_tcpudp.h
 header-y += xt_time.h
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 319f471..b211bb8 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -107,6 +107,7 @@ enum ip_conntrack_events {
 	IPCT_NATSEQADJ = IPCT_SEQADJ,
 	IPCT_SECMARK,		/* new security mark has been set */
 	IPCT_LABEL,		/* new connlabel has been set */
+	IPCT_TCINDEX,		/* new tc_index has been set */
 };
 
 enum ip_conntrack_expect_events {
diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
index c1a4e144..cfdd15f 100644
--- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -53,6 +53,7 @@ enum ctattr_type {
 	CTA_MARK_MASK,
 	CTA_LABELS,
 	CTA_LABELS_MASK,
+	CTA_TC_INDEX,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
diff --git a/include/uapi/linux/netfilter/xt_CONNTCINDEX.h b/include/uapi/linux/netfilter/xt_CONNTCINDEX.h
new file mode 100644
index 0000000..96eccf3
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_CONNTCINDEX.h
@@ -0,0 +1,6 @@
+#ifndef _XT_CONNTCINDEX_H_target
+#define _XT_CONNTCINDEX_H_target
+
+#include <linux/netfilter/xt_conntcindex.h>
+
+#endif /*_XT_CONNTCINDEX_H_target*/
diff --git a/include/uapi/linux/netfilter/xt_TCINDEX.h b/include/uapi/linux/netfilter/xt_TCINDEX.h
new file mode 100644
index 0000000..a35af8b
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_TCINDEX.h
@@ -0,0 +1,6 @@
+#ifndef _XT_TCINDEX_H_target
+#define _XT_TCINDEX_H_target
+
+#include <linux/netfilter/xt_tcindex.h>
+
+#endif /*_XT_TCINDEX_H_target */
diff --git a/include/uapi/linux/netfilter/xt_conntcindex.h b/include/uapi/linux/netfilter/xt_conntcindex.h
new file mode 100644
index 0000000..d82329a
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_conntcindex.h
@@ -0,0 +1,31 @@
+#ifndef _XT_CONNTCINDEX_H
+#define _XT_CONNTCINDEX_H
+
+#include <linux/types.h>
+
+/* Copyright (C) 2015 Allied Telesis Labs NZ
+ * by Luuk Paulussen <luuk.paulussen-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+enum {
+	XT_CONNTCINDEX_SET = 0,
+	XT_CONNTCINDEX_SAVE,
+	XT_CONNTCINDEX_RESTORE
+};
+
+struct xt_conntcindex_tginfo1 {
+	__u16 ctmark, ctmask, nfmask;
+	__u8 mode;
+};
+
+struct xt_conntcindex_mtinfo1 {
+	__u16 mark, mask;
+	__u8 invert;
+};
+
+#endif /*_XT_CONNTCINDEX_H*/
diff --git a/include/uapi/linux/netfilter/xt_tcindex.h b/include/uapi/linux/netfilter/xt_tcindex.h
new file mode 100644
index 0000000..cb012fa
--- /dev/null
+++ b/include/uapi/linux/netfilter/xt_tcindex.h
@@ -0,0 +1,15 @@
+#ifndef _XT_TCINDEX_H
+#define _XT_TCINDEX_H
+
+#include <linux/types.h>
+
+struct xt_tcindex_tginfo1 {
+	__u16 mark, mask;
+};
+
+struct xt_tcindex_mtinfo1 {
+	__u16 mark, mask;
+	__u8 invert;
+};
+
+#endif /*_XT_TCINDEX_H*/
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 4692782..8623157 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -603,6 +603,36 @@ config NETFILTER_XT_CONNMARK
 	ctmark), similarly to the packet mark (nfmark). Using this
 	target and match, you can set and match on this mark.
 
+config NETFILTER_XT_TCINDEX
+	tristate 'tc_index mark target and match support'
+	depends on NETFILTER_ADVANCED
+	depends on NET_SCHED
+	default n
+	---help---
+	This option adds the "TCINDEX" target and "tcindex" match.
+
+	tcindex matching allows you to match packets based on the "tc_index" value
+	in the packet.
+	The target allows you to create rules in the "mangle" table which alter
+	the tc_index field associated with the packet.
+
+	This is an alternative to setting the tc_index field based on the priority
+	fields of the incoming traffic.  In traffic control, this mark can be matched
+	using the tcindex filter.
+
+config NETFILTER_XT_CONNTCINDEX
+	tristate 'ct tc_index mark target and match support'
+	depends on NF_CONNTRACK
+	depends on NF_CONNTRACK_MARK
+	depends on NETFILTER_ADVANCED
+	depends on NET_SCHED
+	default n
+	---help---
+	This option adds the "CONNTCINDEX" target and "conntcindex" match.
+
+	Using this target and match, you can set and match on the tc_index mark in the
+	connection.  This can also be saved/restored to the packet tc_index mark.
+
 config NETFILTER_XT_SET
 	tristate 'set target and match support'
 	depends on IP_SET
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 2293484..d648ae0 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -96,6 +96,8 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 # combos
 obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o
 obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o
+obj-$(CONFIG_NETFILTER_XT_TCINDEX) += xt_tcindex.o
+obj-$(CONFIG_NETFILTER_XT_CONNTCINDEX) += xt_conntcindex.o
 obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o
 obj-$(CONFIG_NETFILTER_XT_NAT) += xt_nat.o
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9f52729..e33a765 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -314,6 +314,21 @@ nla_put_failure:
 #define ctnetlink_dump_mark(a, b) (0)
 #endif
 
+#if defined CONFIG_NET_SCHED && defined CONFIG_NF_CONNTRACK_MARK
+static inline int
+ctnetlink_dump_tcindex(struct sk_buff *skb, const struct nf_conn *ct)
+{
+	if (nla_put_be16(skb, CTA_TC_INDEX, htonl(ct->tc_index)))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+#else
+#define ctnetlink_dump_tcindex(a, b) (0)
+#endif
+
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
 static inline int
 ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
@@ -521,6 +536,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
 	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_mark(skb, ct) < 0 ||
+	    ctnetlink_dump_tcindex(skb, ct) < 0 ||
 	    ctnetlink_dump_secctx(skb, ct) < 0 ||
 	    ctnetlink_dump_labels(skb, ct) < 0 ||
 	    ctnetlink_dump_id(skb, ct) < 0 ||
@@ -749,7 +765,13 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
 	if ((events & (1 << IPCT_MARK) || ct->mark)
 	    && ctnetlink_dump_mark(skb, ct) < 0)
 		goto nla_put_failure;
-#endif
+
+#ifdef CONFIG_NET_SCHED
+	if ((events & (1 << IPCT_TCINDEX) || ct->tc_index) &&
+	    ctnetlink_dump_tcindex(skb, ct) < 0)
+		goto nla_put_failure;
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 	rcu_read_unlock();
 
 	nlmsg_end(skb, nlh);
@@ -1092,6 +1114,7 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
 				    .len = NF_CT_LABELS_MAX_SIZE },
 	[CTA_LABELS_MASK]	= { .type = NLA_BINARY,
 				    .len = NF_CT_LABELS_MAX_SIZE },
+	[CTA_TC_INDEX]		= { .type = NLA_U16 },
 };
 
 static int ctnetlink_flush_conntrack(struct net *net,
@@ -1697,7 +1720,12 @@ ctnetlink_change_conntrack(struct nf_conn *ct,
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
-#endif
+#ifdef CONFIG_NET_SCHED
+	if (cda[CTA_TC_INDEX])
+		ct->tc_index = ntohs(nla_get_be16(cda[CTA_TC_INDEX]));
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
 
 	if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) {
 		err = ctnetlink_change_seq_adj(ct, cda);
@@ -1824,7 +1852,11 @@ ctnetlink_create_conntrack(struct net *net,
 #if defined(CONFIG_NF_CONNTRACK_MARK)
 	if (cda[CTA_MARK])
 		ct->mark = ntohl(nla_get_be32(cda[CTA_MARK]));
-#endif
+#ifdef CONFIG_NET_SCHED
+	if (cda[CTA_TC_INDEX])
+		ct->tc_index = ntohs(nla_get_be16(cda[CTA_TC_INDEX]));
+#endif /* CONFIG_NET_SCHED */
+#endif /* CONFIG_NF_CONNTRACK_MARK */
 
 	/* setup master conntrack: this is a confirmed expectation */
 	if (cda[CTA_TUPLE_MASTER]) {
diff --git a/net/netfilter/xt_conntcindex.c b/net/netfilter/xt_conntcindex.c
new file mode 100644
index 0000000..1b37562
--- /dev/null
+++ b/net/netfilter/xt_conntcindex.c
@@ -0,0 +1,165 @@
+/*
+ * xt_conntcindex - Netfilter module to operate on connection tc_index marks
+ *
+ * Copyright (C) 2015 Allied Telesis Labs NZ
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Heavily based on xt_connmark.c
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_conntcindex.h>
+
+MODULE_AUTHOR("Luuk Paulussen <luuk.paulussen-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>");
+MODULE_DESCRIPTION("Xtables: connection tc_index mark operations");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_CONNTCINDEX");
+MODULE_ALIAS("ip6t_CONNTCINDEX");
+MODULE_ALIAS("ipt_conntcindex");
+MODULE_ALIAS("ip6t_conntcindex");
+
+static unsigned int
+conntcindex_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_conntcindex_tginfo1 *info = par->targinfo;
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct;
+	u32 newmark;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct)
+		return XT_CONTINUE;
+
+	switch (info->mode) {
+	case XT_CONNTCINDEX_SET:
+		newmark = (ct->tc_index & ~info->ctmask) ^ info->ctmark;
+		if (ct->tc_index != newmark) {
+			ct->tc_index = newmark;
+			nf_conntrack_event_cache(IPCT_TCINDEX, ct);
+		}
+		break;
+	case XT_CONNTCINDEX_SAVE:
+		newmark = (ct->tc_index & ~info->ctmask) ^
+			  (skb->tc_index & info->nfmask);
+		if (ct->tc_index != newmark) {
+			ct->tc_index = newmark;
+			nf_conntrack_event_cache(IPCT_TCINDEX, ct);
+		}
+		break;
+	case XT_CONNTCINDEX_RESTORE:
+		newmark = (skb->tc_index & ~info->nfmask) ^
+			  (ct->tc_index & info->ctmask);
+		skb->tc_index = newmark;
+		break;
+	}
+
+	return XT_CONTINUE;
+}
+
+static int conntcindex_tg_check(const struct xt_tgchk_param *par)
+{
+	int ret;
+
+	ret = nf_ct_l3proto_try_module_get(par->family);
+	if (ret < 0)
+		pr_info("cannot load conntrack support for proto=%u\n",
+			par->family);
+	return ret;
+}
+
+static void conntcindex_tg_destroy(const struct xt_tgdtor_param *par)
+{
+	nf_ct_l3proto_module_put(par->family);
+}
+
+static bool
+conntcindex_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_conntcindex_mtinfo1 *info = par->matchinfo;
+	enum ip_conntrack_info ctinfo;
+	const struct nf_conn *ct;
+
+	ct = nf_ct_get(skb, &ctinfo);
+	if (!ct)
+		return false;
+
+	return ((ct->tc_index & info->mask) == info->mark) ^ info->invert;
+}
+
+static int conntcindex_mt_check(const struct xt_mtchk_param *par)
+{
+	int ret;
+
+	ret = nf_ct_l3proto_try_module_get(par->family);
+	if (ret < 0)
+		pr_info("cannot load conntrack support for proto=%u\n",
+			par->family);
+	return ret;
+}
+
+static void conntcindex_mt_destroy(const struct xt_mtdtor_param *par)
+{
+	nf_ct_l3proto_module_put(par->family);
+}
+
+static struct xt_target conntcindex_tg_reg __read_mostly = {
+	.name           = "CONNTCINDEX",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.checkentry     = conntcindex_tg_check,
+	.target         = conntcindex_tg,
+	.targetsize     = sizeof(struct xt_conntcindex_tginfo1),
+	.destroy        = conntcindex_tg_destroy,
+	.me             = THIS_MODULE,
+};
+
+static struct xt_match conntcindex_mt_reg __read_mostly = {
+	.name           = "conntcindex",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.checkentry     = conntcindex_mt_check,
+	.match          = conntcindex_mt,
+	.matchsize      = sizeof(struct xt_conntcindex_mtinfo1),
+	.destroy        = conntcindex_mt_destroy,
+	.me             = THIS_MODULE,
+};
+
+static int __init conntcindex_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_target(&conntcindex_tg_reg);
+	if (ret < 0)
+		return ret;
+	ret = xt_register_match(&conntcindex_mt_reg);
+	if (ret < 0) {
+		xt_unregister_target(&conntcindex_tg_reg);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit conntcindex_mt_exit(void)
+{
+	xt_unregister_match(&conntcindex_mt_reg);
+	xt_unregister_target(&conntcindex_tg_reg);
+}
+
+module_init(conntcindex_mt_init);
+module_exit(conntcindex_mt_exit);
diff --git a/net/netfilter/xt_tcindex.c b/net/netfilter/xt_tcindex.c
new file mode 100644
index 0000000..7de29cd
--- /dev/null
+++ b/net/netfilter/xt_tcindex.c
@@ -0,0 +1,84 @@
+/*
+ *	xt_tcindex - Netfilter module to match/tag on tc_index mark value
+ *
+ *	(C) 2015 Allied Telesis Labs NZ.
+  *
+ *	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.
+ *
+ *	Heavily based on xt_mark.c
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/xt_tcindex.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Luuk Paulussen <luuk.paulussen-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>");
+MODULE_DESCRIPTION("Xtables: packet tc_index mark operations");
+MODULE_ALIAS("ipt_tcindex");
+MODULE_ALIAS("ip6t_tcindex");
+MODULE_ALIAS("ipt_TCINDEX");
+MODULE_ALIAS("ip6t_TCINDEX");
+
+static unsigned int
+tcindex_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_tcindex_tginfo1 *info = par->targinfo;
+
+	skb->tc_index = (skb->tc_index & ~info->mask) ^ info->mark;
+	return XT_CONTINUE;
+}
+
+static bool
+tcindex_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_tcindex_mtinfo1 *info = par->matchinfo;
+
+	return ((skb->tc_index & info->mask) == info->mark) ^ info->invert;
+}
+
+static struct xt_target tcindex_tg_reg __read_mostly = {
+	.name           = "TCINDEX",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.target         = tcindex_tg,
+	.targetsize     = sizeof(struct xt_tcindex_tginfo1),
+	.me             = THIS_MODULE,
+};
+
+static struct xt_match tcindex_mt_reg __read_mostly = {
+	.name           = "tcindex",
+	.revision       = 1,
+	.family         = NFPROTO_UNSPEC,
+	.match          = tcindex_mt,
+	.matchsize      = sizeof(struct xt_tcindex_mtinfo1),
+	.me             = THIS_MODULE,
+};
+
+static int __init tcindex_mt_init(void)
+{
+	int ret;
+
+	ret = xt_register_target(&tcindex_tg_reg);
+	if (ret < 0)
+		return ret;
+	ret = xt_register_match(&tcindex_mt_reg);
+	if (ret < 0) {
+		xt_unregister_target(&tcindex_tg_reg);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit tcindex_mt_exit(void)
+{
+	xt_unregister_match(&tcindex_mt_reg);
+	xt_unregister_target(&tcindex_tg_reg);
+}
+
+module_init(tcindex_mt_init);
+module_exit(tcindex_mt_exit);
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-12-22 21:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-16  0:20 Add tcindex to conntrack and add netfilter target/matches Luuk Paulussen
2015-12-16  0:20 ` [PATCH] " Luuk Paulussen
2015-12-17  5:21   ` kbuild test robot
2015-12-21 22:34     ` [PATCH v2] net-next: " Luuk Paulussen
2015-12-22 21:50 (unknown), Luuk Paulussen
     [not found] ` <1450821040-18837-1-git-send-email-luuk.paulussen-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>
2015-12-22 21:50   ` [PATCH v2] net-next: Add tcindex to conntrack and add netfilter target/matches Luuk Paulussen

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.