netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching
@ 2019-12-18 11:05 Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 1/9] netfilter: nft_meta: move time handling to helper Florian Westphal
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel

Martin Willi recently proposed addition of new xt_slavedev module to
allow matching the real interface within a VRF domain.

This adds an nft equivalent:

meta sdif "realdev" accept
meta sdifname "realdev" accept

In case packet had no vrf slave, sdif stores 0 or "" name, just
like 'oif/oifname' would on input.

sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
as it depends on ip(6) stack parsing/storing info in skb->cb[].

Because meta main eval function is now exceeding more than 200 LOC,
the first patches are diet work to debloat the function by using
helpers where appropriate.

Last patch adds the sdif/sdifname functionality.

Function                                     old     new   delta
nft_meta_get_eval_pkttype_lo                   -     588    +588
nft_meta_get_eval_time                         -     404    +404
nft_meta_get_eval_skugid                       -     397    +397
nft_meta_get_eval_cgroup                       -     234    +234
nft_meta_get_eval_sif                          -     148    +148
nft_meta_get_eval_kind                         -     138    +138
nft_meta_get_eval_sifname                      -      91     +91
nft_meta_get_validate                        111     169     +58
nft_prandom_u32                                -      20     +20
nft_meta_get_eval                           2904    1261   -1643
Total: Before=6076, After=6511, chg +7.16%



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

* [PATCH nf-next 1/9] netfilter: nft_meta: move time handling to helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 2/9] netfilter: nft_meta: move pkttype " Florian Westphal
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

reduce size of the (large) meta evaluation function.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 9740b554fdb3..ba74f3ee7264 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -33,8 +33,9 @@
 
 static DEFINE_PER_CPU(struct rnd_state, nft_prandom_state);
 
-static u8 nft_meta_weekday(time64_t secs)
+static u8 nft_meta_weekday(void)
 {
+	time64_t secs = ktime_get_real_seconds();
 	unsigned int dse;
 	u8 wday;
 
@@ -56,6 +57,25 @@ static u32 nft_meta_hour(time64_t secs)
 		+ tm.tm_sec;
 }
 
+static noinline_for_stack void
+nft_meta_get_eval_time(enum nft_meta_keys key,
+		       u32 *dest)
+{
+	switch (key) {
+	case NFT_META_TIME_NS:
+		nft_reg_store64(dest, ktime_get_real_ns());
+		break;
+	case NFT_META_TIME_DAY:
+		nft_reg_store8(dest, nft_meta_weekday());
+		break;
+	case NFT_META_TIME_HOUR:
+		*dest = nft_meta_hour(ktime_get_real_seconds());
+		break;
+	default:
+		break;
+	}
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -247,13 +267,9 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 		strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
 		break;
 	case NFT_META_TIME_NS:
-		nft_reg_store64(dest, ktime_get_real_ns());
-		break;
 	case NFT_META_TIME_DAY:
-		nft_reg_store8(dest, nft_meta_weekday(ktime_get_real_seconds()));
-		break;
 	case NFT_META_TIME_HOUR:
-		*dest = nft_meta_hour(ktime_get_real_seconds());
+		nft_meta_get_eval_time(priv->key, dest);
 		break;
 	default:
 		WARN_ON(1);
-- 
2.24.1


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

* [PATCH nf-next 2/9] netfilter: nft_meta: move pkttype handling to helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 1/9] netfilter: nft_meta: move time handling to helper Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 3/9] netfilter: nft_meta: move sk uid/git " Florian Westphal
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

When pkttype is loopback, nft_meta performs guesswork to detect
broad/multicast packets. Place this in a helper, this is hardly a hot path.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 90 +++++++++++++++++++++++-----------------
 1 file changed, 51 insertions(+), 39 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index ba74f3ee7264..fe49b27dfa87 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -76,6 +76,56 @@ nft_meta_get_eval_time(enum nft_meta_keys key,
 	}
 }
 
+static noinline bool
+nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt,
+			     u32 *dest)
+{
+	const struct sk_buff *skb = pkt->skb;
+
+	switch (nft_pf(pkt)) {
+	case NFPROTO_IPV4:
+		if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+			nft_reg_store8(dest, PACKET_MULTICAST);
+		else
+			nft_reg_store8(dest, PACKET_BROADCAST);
+		break;
+	case NFPROTO_IPV6:
+		nft_reg_store8(dest, PACKET_MULTICAST);
+		break;
+	case NFPROTO_NETDEV:
+		switch (skb->protocol) {
+		case htons(ETH_P_IP): {
+			int noff = skb_network_offset(skb);
+			struct iphdr *iph, _iph;
+
+			iph = skb_header_pointer(skb, noff,
+						 sizeof(_iph), &_iph);
+			if (!iph)
+				return false;
+
+			if (ipv4_is_multicast(iph->daddr))
+				nft_reg_store8(dest, PACKET_MULTICAST);
+			else
+				nft_reg_store8(dest, PACKET_BROADCAST);
+
+			break;
+		}
+		case htons(ETH_P_IPV6):
+			nft_reg_store8(dest, PACKET_MULTICAST);
+			break;
+		default:
+			WARN_ON_ONCE(1);
+			return false;
+		}
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return false;
+	}
+
+	return true;
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -183,46 +233,8 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 			break;
 		}
 
-		switch (nft_pf(pkt)) {
-		case NFPROTO_IPV4:
-			if (ipv4_is_multicast(ip_hdr(skb)->daddr))
-				nft_reg_store8(dest, PACKET_MULTICAST);
-			else
-				nft_reg_store8(dest, PACKET_BROADCAST);
-			break;
-		case NFPROTO_IPV6:
-			nft_reg_store8(dest, PACKET_MULTICAST);
-			break;
-		case NFPROTO_NETDEV:
-			switch (skb->protocol) {
-			case htons(ETH_P_IP): {
-				int noff = skb_network_offset(skb);
-				struct iphdr *iph, _iph;
-
-				iph = skb_header_pointer(skb, noff,
-							 sizeof(_iph), &_iph);
-				if (!iph)
-					goto err;
-
-				if (ipv4_is_multicast(iph->daddr))
-					nft_reg_store8(dest, PACKET_MULTICAST);
-				else
-					nft_reg_store8(dest, PACKET_BROADCAST);
-
-				break;
-			}
-			case htons(ETH_P_IPV6):
-				nft_reg_store8(dest, PACKET_MULTICAST);
-				break;
-			default:
-				WARN_ON_ONCE(1);
-				goto err;
-			}
-			break;
-		default:
-			WARN_ON_ONCE(1);
+		if (!nft_meta_get_eval_pkttype_lo(pkt, dest))
 			goto err;
-		}
 		break;
 	case NFT_META_CPU:
 		*dest = raw_smp_processor_id();
-- 
2.24.1


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

* [PATCH nf-next 3/9] netfilter: nft_meta: move sk uid/git handling to helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 1/9] netfilter: nft_meta: move time handling to helper Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 2/9] netfilter: nft_meta: move pkttype " Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 4/9] netfilter: nft_meta: move cgroup " Florian Westphal
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Not a hot path.  Also, both have copy&paste case statements,
so use a common helper for both.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 65 ++++++++++++++++++++++------------------
 1 file changed, 36 insertions(+), 29 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index fe49b27dfa87..1b32440ec2e6 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -126,6 +126,41 @@ nft_meta_get_eval_pkttype_lo(const struct nft_pktinfo *pkt,
 	return true;
 }
 
+static noinline bool
+nft_meta_get_eval_skugid(enum nft_meta_keys key,
+			 u32 *dest,
+			 const struct nft_pktinfo *pkt)
+{
+	struct sock *sk = skb_to_full_sk(pkt->skb);
+	struct socket *sock;
+
+	if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
+		return false;
+
+	read_lock_bh(&sk->sk_callback_lock);
+	sock = sk->sk_socket;
+	if (!sock || !sock->file) {
+		read_unlock_bh(&sk->sk_callback_lock);
+		return false;
+	}
+
+	switch (key) {
+	case NFT_META_SKUID:
+		*dest = from_kuid_munged(&init_user_ns,
+					 sock->file->f_cred->fsuid);
+		break;
+	case NFT_META_SKGID:
+		*dest =	from_kgid_munged(&init_user_ns,
+					 sock->file->f_cred->fsgid);
+		break;
+	default:
+		break;
+	}
+
+	read_unlock_bh(&sk->sk_callback_lock);
+	return true;
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -180,37 +215,9 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 		nft_reg_store16(dest, out->type);
 		break;
 	case NFT_META_SKUID:
-		sk = skb_to_full_sk(skb);
-		if (!sk || !sk_fullsock(sk) ||
-		    !net_eq(nft_net(pkt), sock_net(sk)))
-			goto err;
-
-		read_lock_bh(&sk->sk_callback_lock);
-		if (sk->sk_socket == NULL ||
-		    sk->sk_socket->file == NULL) {
-			read_unlock_bh(&sk->sk_callback_lock);
-			goto err;
-		}
-
-		*dest =	from_kuid_munged(&init_user_ns,
-				sk->sk_socket->file->f_cred->fsuid);
-		read_unlock_bh(&sk->sk_callback_lock);
-		break;
 	case NFT_META_SKGID:
-		sk = skb_to_full_sk(skb);
-		if (!sk || !sk_fullsock(sk) ||
-		    !net_eq(nft_net(pkt), sock_net(sk)))
+		if (!nft_meta_get_eval_skugid(priv->key, dest, pkt))
 			goto err;
-
-		read_lock_bh(&sk->sk_callback_lock);
-		if (sk->sk_socket == NULL ||
-		    sk->sk_socket->file == NULL) {
-			read_unlock_bh(&sk->sk_callback_lock);
-			goto err;
-		}
-		*dest =	from_kgid_munged(&init_user_ns,
-				 sk->sk_socket->file->f_cred->fsgid);
-		read_unlock_bh(&sk->sk_callback_lock);
 		break;
 #ifdef CONFIG_IP_ROUTE_CLASSID
 	case NFT_META_RTCLASSID: {
-- 
2.24.1


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

* [PATCH nf-next 4/9] netfilter: nft_meta: move cgroup handling to helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (2 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 3/9] netfilter: nft_meta: move sk uid/git " Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 5/9] netfilter: nft_meta: move interface kind " Florian Westphal
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Reduce size of main eval function.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 1b32440ec2e6..3fca1c3ec361 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -161,6 +161,20 @@ nft_meta_get_eval_skugid(enum nft_meta_keys key,
 	return true;
 }
 
+#ifdef CONFIG_CGROUP_NET_CLASSID
+static noinline bool
+nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt)
+{
+	struct sock *sk = skb_to_full_sk(pkt->skb);
+
+	if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
+		return false;
+
+	*dest = sock_cgroup_classid(&sk->sk_cgrp_data);
+	return true;
+}
+#endif
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -168,7 +182,6 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 	const struct nft_meta *priv = nft_expr_priv(expr);
 	const struct sk_buff *skb = pkt->skb;
 	const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
-	struct sock *sk;
 	u32 *dest = &regs->data[priv->dreg];
 
 	switch (priv->key) {
@@ -258,11 +271,8 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 		break;
 #ifdef CONFIG_CGROUP_NET_CLASSID
 	case NFT_META_CGROUP:
-		sk = skb_to_full_sk(skb);
-		if (!sk || !sk_fullsock(sk) ||
-		    !net_eq(nft_net(pkt), sock_net(sk)))
+		if (!nft_meta_get_eval_cgroup(dest, pkt))
 			goto err;
-		*dest = sock_cgroup_classid(&sk->sk_cgrp_data);
 		break;
 #endif
 	case NFT_META_PRANDOM: {
-- 
2.24.1


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

* [PATCH nf-next 5/9] netfilter: nft_meta: move interface kind handling to helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (3 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 4/9] netfilter: nft_meta: move cgroup " Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 6/9] netfilter: nft_meta: move all interface related keys " Florian Westphal
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

checkpatch complains about == NULL checks in original code,
so use !in instead.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 3fca1c3ec361..2f7cc64b0c15 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -175,6 +175,30 @@ nft_meta_get_eval_cgroup(u32 *dest, const struct nft_pktinfo *pkt)
 }
 #endif
 
+static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
+					    u32 *dest,
+					    const struct nft_pktinfo *pkt)
+{
+	const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
+
+	switch (key) {
+	case NFT_META_IIFKIND:
+		if (!in || !in->rtnl_link_ops)
+			return false;
+		strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
+		break;
+	case NFT_META_OIFKIND:
+		if (!out || !out->rtnl_link_ops)
+			return false;
+		strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -286,14 +310,9 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 		break;
 #endif
 	case NFT_META_IIFKIND:
-		if (in == NULL || in->rtnl_link_ops == NULL)
-			goto err;
-		strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
-		break;
 	case NFT_META_OIFKIND:
-		if (out == NULL || out->rtnl_link_ops == NULL)
+		if (!nft_meta_get_eval_kind(priv->key, dest, pkt))
 			goto err;
-		strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
 		break;
 	case NFT_META_TIME_NS:
 	case NFT_META_TIME_DAY:
-- 
2.24.1


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

* [PATCH nf-next 6/9] netfilter: nft_meta: move all interface related keys to helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (4 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 5/9] netfilter: nft_meta: move interface kind " Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 7/9] netfilter: nft_meta: place prandom handling in a helper Florian Westphal
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Reduces repetiveness and reduces size of meta eval function.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 95 +++++++++++++++++++++++++++++-----------
 1 file changed, 70 insertions(+), 25 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 2f7cc64b0c15..022f1473ddd1 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -199,13 +199,79 @@ static noinline bool nft_meta_get_eval_kind(enum nft_meta_keys key,
 	return true;
 }
 
+static void nft_meta_store_ifindex(u32 *dest, const struct net_device *dev)
+{
+	*dest = dev ? dev->ifindex : 0;
+}
+
+static void nft_meta_store_ifname(u32 *dest, const struct net_device *dev)
+{
+	strncpy((char *)dest, dev ? dev->name : "", IFNAMSIZ);
+}
+
+static bool nft_meta_store_iftype(u32 *dest, const struct net_device *dev)
+{
+	if (!dev)
+		return false;
+
+	nft_reg_store16(dest, dev->type);
+	return true;
+}
+
+static bool nft_meta_store_ifgroup(u32 *dest, const struct net_device *dev)
+{
+	if (!dev)
+		return false;
+
+	*dest = dev->group;
+	return true;
+}
+
+static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
+				     const struct nft_pktinfo *pkt)
+{
+	switch (key) {
+	case NFT_META_IIFNAME:
+		nft_meta_store_ifname(dest, nft_in(pkt));
+		break;
+	case NFT_META_OIFNAME:
+		nft_meta_store_ifname(dest, nft_out(pkt));
+		break;
+	case NFT_META_IIF:
+		nft_meta_store_ifindex(dest, nft_in(pkt));
+		break;
+	case NFT_META_OIF:
+		nft_meta_store_ifindex(dest, nft_out(pkt));
+		break;
+	case NFT_META_IIFTYPE:
+		if (!nft_meta_store_iftype(dest, nft_in(pkt)))
+			return false;
+		break;
+	case NFT_META_OIFTYPE:
+		if (!nft_meta_store_iftype(dest, nft_out(pkt)))
+			return false;
+		break;
+	case NFT_META_IIFGROUP:
+		if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
+			return false;
+		break;
+	case NFT_META_OIFGROUP:
+		if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
+			return false;
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
 {
 	const struct nft_meta *priv = nft_expr_priv(expr);
 	const struct sk_buff *skb = pkt->skb;
-	const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
 	u32 *dest = &regs->data[priv->dreg];
 
 	switch (priv->key) {
@@ -230,26 +296,15 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 		*dest = skb->mark;
 		break;
 	case NFT_META_IIF:
-		*dest = in ? in->ifindex : 0;
-		break;
 	case NFT_META_OIF:
-		*dest = out ? out->ifindex : 0;
-		break;
 	case NFT_META_IIFNAME:
-		strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
-		break;
 	case NFT_META_OIFNAME:
-		strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
-		break;
 	case NFT_META_IIFTYPE:
-		if (in == NULL)
-			goto err;
-		nft_reg_store16(dest, in->type);
-		break;
 	case NFT_META_OIFTYPE:
-		if (out == NULL)
+	case NFT_META_IIFGROUP:
+	case NFT_META_OIFGROUP:
+		if (!nft_meta_get_eval_ifname(priv->key, dest, pkt))
 			goto err;
-		nft_reg_store16(dest, out->type);
 		break;
 	case NFT_META_SKUID:
 	case NFT_META_SKGID:
@@ -283,16 +338,6 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 	case NFT_META_CPU:
 		*dest = raw_smp_processor_id();
 		break;
-	case NFT_META_IIFGROUP:
-		if (in == NULL)
-			goto err;
-		*dest = in->group;
-		break;
-	case NFT_META_OIFGROUP:
-		if (out == NULL)
-			goto err;
-		*dest = out->group;
-		break;
 #ifdef CONFIG_CGROUP_NET_CLASSID
 	case NFT_META_CGROUP:
 		if (!nft_meta_get_eval_cgroup(dest, pkt))
-- 
2.24.1


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

* [PATCH nf-next 7/9] netfilter: nft_meta: place prandom handling in a helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (5 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 6/9] netfilter: nft_meta: move all interface related keys " Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 8/9] netfilter: nft_meta: place rtclassid " Florian Westphal
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Move this out of the main eval loop, the numgen expression
provides a better alternative to meta random.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 022f1473ddd1..ac6fc95387dc 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -266,6 +266,13 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
 	return true;
 }
 
+static noinline u32 nft_prandom_u32(void)
+{
+	struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);
+
+	return prandom_u32_state(state);
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -344,11 +351,9 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 			goto err;
 		break;
 #endif
-	case NFT_META_PRANDOM: {
-		struct rnd_state *state = this_cpu_ptr(&nft_prandom_state);
-		*dest = prandom_u32_state(state);
+	case NFT_META_PRANDOM:
+		*dest = nft_prandom_u32();
 		break;
-	}
 #ifdef CONFIG_XFRM
 	case NFT_META_SECPATH:
 		nft_reg_store8(dest, secpath_exists(skb));
-- 
2.24.1


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

* [PATCH nf-next 8/9] netfilter: nft_meta: place rtclassid handling in a helper
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (6 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 7/9] netfilter: nft_meta: place prandom handling in a helper Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-18 11:05 ` [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching Florian Westphal
  2019-12-26 16:42 ` [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Pablo Neira Ayuso
  9 siblings, 0 replies; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

skb_dst is an inline helper with a WARN_ON(), so this is a bit more code
than it looks like.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_meta.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index ac6fc95387dc..fb1a571db924 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -273,6 +273,20 @@ static noinline u32 nft_prandom_u32(void)
 	return prandom_u32_state(state);
 }
 
+#ifdef CONFIG_IP_ROUTE_CLASSID
+static noinline bool
+nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
+{
+	const struct dst_entry *dst = skb_dst(skb);
+
+	if (!dst)
+		return false;
+
+	*dest = dst->tclassid;
+	return true;
+}
+#endif
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -319,14 +333,10 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 			goto err;
 		break;
 #ifdef CONFIG_IP_ROUTE_CLASSID
-	case NFT_META_RTCLASSID: {
-		const struct dst_entry *dst = skb_dst(skb);
-
-		if (dst == NULL)
+	case NFT_META_RTCLASSID:
+		if (!nft_meta_get_eval_rtclassid(skb, dest))
 			goto err;
-		*dest = dst->tclassid;
 		break;
-	}
 #endif
 #ifdef CONFIG_NETWORK_SECMARK
 	case NFT_META_SECMARK:
-- 
2.24.1


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

* [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (7 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 8/9] netfilter: nft_meta: place rtclassid " Florian Westphal
@ 2019-12-18 11:05 ` Florian Westphal
  2019-12-19 16:46   ` David Ahern
  2019-12-26 16:42 ` [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Pablo Neira Ayuso
  9 siblings, 1 reply; 14+ messages in thread
From: Florian Westphal @ 2019-12-18 11:05 UTC (permalink / raw)
  To: netfilter-devel
  Cc: Florian Westphal, Martin Willi, David Ahern, Shrijeet Mukherjee

Allow to match on vrf slave ifindex or name.

In case there was no slave interface involved, store 0 in the
destination register just like existing iif/oif matching.

sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
as it depends on ip(6) stack parsing/storing info in skb->cb[].

Cc: Martin Willi <martin@strongswan.org>
Cc: David Ahern <dsahern@kernel.org>
Cc: Shrijeet Mukherjee <shrijeet@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/uapi/linux/netfilter/nf_tables.h |  4 ++
 net/netfilter/nft_meta.c                 | 76 +++++++++++++++++++++---
 2 files changed, 73 insertions(+), 7 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index bb9b049310df..e237ecbdcd8a 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -805,6 +805,8 @@ enum nft_exthdr_attributes {
  * @NFT_META_TIME_NS: time since epoch (in nanoseconds)
  * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)
  * @NFT_META_TIME_HOUR: hour of day (in seconds)
+ * @NFT_META_SDIF: slave device interface index
+ * @NFT_META_SDIFNAME: slave device interface name
  */
 enum nft_meta_keys {
 	NFT_META_LEN,
@@ -840,6 +842,8 @@ enum nft_meta_keys {
 	NFT_META_TIME_NS,
 	NFT_META_TIME_DAY,
 	NFT_META_TIME_HOUR,
+	NFT_META_SDIF,
+	NFT_META_SDIFNAME,
 };
 
 /**
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index fb1a571db924..951b6e87ed5d 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -17,6 +17,7 @@
 #include <linux/smp.h>
 #include <linux/static_key.h>
 #include <net/dst.h>
+#include <net/ip.h>
 #include <net/sock.h>
 #include <net/tcp_states.h> /* for TCP_TIME_WAIT */
 #include <net/netfilter/nf_tables.h>
@@ -287,6 +288,28 @@ nft_meta_get_eval_rtclassid(const struct sk_buff *skb, u32 *dest)
 }
 #endif
 
+static noinline u32 nft_meta_get_eval_sdif(const struct nft_pktinfo *pkt)
+{
+	switch (nft_pf(pkt)) {
+	case NFPROTO_IPV4:
+		return inet_sdif(pkt->skb);
+	case NFPROTO_IPV6:
+		return inet6_sdif(pkt->skb);
+	}
+
+	return 0;
+}
+
+static noinline void
+nft_meta_get_eval_sdifname(u32 *dest, const struct nft_pktinfo *pkt)
+{
+	u32 sdif = nft_meta_get_eval_sdif(pkt);
+	const struct net_device *dev;
+
+	dev = sdif ? dev_get_by_index_rcu(nft_net(pkt), sdif) : NULL;
+	nft_meta_store_ifname(dest, dev);
+}
+
 void nft_meta_get_eval(const struct nft_expr *expr,
 		       struct nft_regs *regs,
 		       const struct nft_pktinfo *pkt)
@@ -379,6 +402,12 @@ void nft_meta_get_eval(const struct nft_expr *expr,
 	case NFT_META_TIME_HOUR:
 		nft_meta_get_eval_time(priv->key, dest);
 		break;
+	case NFT_META_SDIF:
+		*dest = nft_meta_get_eval_sdif(pkt);
+		break;
+	case NFT_META_SDIFNAME:
+		nft_meta_get_eval_sdifname(dest, pkt);
+		break;
 	default:
 		WARN_ON(1);
 		goto err;
@@ -459,6 +488,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
 	case NFT_META_MARK:
 	case NFT_META_IIF:
 	case NFT_META_OIF:
+	case NFT_META_SDIF:
 	case NFT_META_SKUID:
 	case NFT_META_SKGID:
 #ifdef CONFIG_IP_ROUTE_CLASSID
@@ -480,6 +510,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
 	case NFT_META_OIFNAME:
 	case NFT_META_IIFKIND:
 	case NFT_META_OIFKIND:
+	case NFT_META_SDIFNAME:
 		len = IFNAMSIZ;
 		break;
 	case NFT_META_PRANDOM:
@@ -510,16 +541,28 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
 }
 EXPORT_SYMBOL_GPL(nft_meta_get_init);
 
-static int nft_meta_get_validate(const struct nft_ctx *ctx,
-				 const struct nft_expr *expr,
-				 const struct nft_data **data)
+static int nft_meta_get_validate_sdif(const struct nft_ctx *ctx)
 {
-#ifdef CONFIG_XFRM
-	const struct nft_meta *priv = nft_expr_priv(expr);
 	unsigned int hooks;
 
-	if (priv->key != NFT_META_SECPATH)
-		return 0;
+	switch (ctx->family) {
+	case NFPROTO_IPV4:
+	case NFPROTO_IPV6:
+	case NFPROTO_INET:
+		hooks = (1 << NF_INET_LOCAL_IN) |
+			(1 << NF_INET_FORWARD);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return nft_chain_validate_hooks(ctx->chain, hooks);
+}
+
+static int nft_meta_get_validate_xfrm(const struct nft_ctx *ctx)
+{
+#ifdef CONFIG_XFRM
+	unsigned int hooks;
 
 	switch (ctx->family) {
 	case NFPROTO_NETDEV:
@@ -542,6 +585,25 @@ static int nft_meta_get_validate(const struct nft_ctx *ctx,
 #endif
 }
 
+static int nft_meta_get_validate(const struct nft_ctx *ctx,
+				 const struct nft_expr *expr,
+				 const struct nft_data **data)
+{
+	const struct nft_meta *priv = nft_expr_priv(expr);
+
+	switch (priv->key) {
+	case NFT_META_SECPATH:
+		return nft_meta_get_validate_xfrm(ctx);
+	case NFT_META_SDIF:
+	case NFT_META_SDIFNAME:
+		return nft_meta_get_validate_sdif(ctx);
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 int nft_meta_set_validate(const struct nft_ctx *ctx,
 			  const struct nft_expr *expr,
 			  const struct nft_data **data)
-- 
2.24.1


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

* Re: [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching
  2019-12-18 11:05 ` [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching Florian Westphal
@ 2019-12-19 16:46   ` David Ahern
  2019-12-19 17:08     ` Florian Westphal
  0 siblings, 1 reply; 14+ messages in thread
From: David Ahern @ 2019-12-19 16:46 UTC (permalink / raw)
  To: Florian Westphal, netfilter-devel
  Cc: Martin Willi, David Ahern, Shrijeet Mukherjee, Roopa Prabhu,
	Benjamin Poirier

On 12/18/19 4:05 AM, Florian Westphal wrote:
> Allow to match on vrf slave ifindex or name.
> 
> In case there was no slave interface involved, store 0 in the
> destination register just like existing iif/oif matching.
> 
> sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
> as it depends on ip(6) stack parsing/storing info in skb->cb[].
> 
> Cc: Martin Willi <martin@strongswan.org>
> Cc: David Ahern <dsahern@kernel.org>
> Cc: Shrijeet Mukherjee <shrijeet@gmail.com>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  include/uapi/linux/netfilter/nf_tables.h |  4 ++
>  net/netfilter/nft_meta.c                 | 76 +++++++++++++++++++++---
>  2 files changed, 73 insertions(+), 7 deletions(-)
> 

do you have an example that you can share?

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

* Re: [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching
  2019-12-19 16:46   ` David Ahern
@ 2019-12-19 17:08     ` Florian Westphal
  2019-12-20  1:27       ` David Ahern
  0 siblings, 1 reply; 14+ messages in thread
From: Florian Westphal @ 2019-12-19 17:08 UTC (permalink / raw)
  To: David Ahern
  Cc: Florian Westphal, netfilter-devel, Martin Willi, David Ahern,
	Shrijeet Mukherjee, Roopa Prabhu, Benjamin Poirier

David Ahern <dsahern@gmail.com> wrote:
> On 12/18/19 4:05 AM, Florian Westphal wrote:
> > Allow to match on vrf slave ifindex or name.
> > 
> > In case there was no slave interface involved, store 0 in the
> > destination register just like existing iif/oif matching.
> > 
> > sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
> > as it depends on ip(6) stack parsing/storing info in skb->cb[].
> > 
> > Cc: Martin Willi <martin@strongswan.org>
> > Cc: David Ahern <dsahern@kernel.org>
> > Cc: Shrijeet Mukherjee <shrijeet@gmail.com>
> > Signed-off-by: Florian Westphal <fw@strlen.de>
> > ---
> >  include/uapi/linux/netfilter/nf_tables.h |  4 ++
> >  net/netfilter/nft_meta.c                 | 76 +++++++++++++++++++++---
> >  2 files changed, 73 insertions(+), 7 deletions(-)
> > 
> 
> do you have an example that you can share?

nft add rule inet filter input meta sdifname "eth0" accept

so its similar to existing iif(name) that test for the input device.

This is the nft equivalent for the "slavedev" match that Martin proposed
here:

http://patchwork.ozlabs.org/patch/1211435/

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

* Re: [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching
  2019-12-19 17:08     ` Florian Westphal
@ 2019-12-20  1:27       ` David Ahern
  0 siblings, 0 replies; 14+ messages in thread
From: David Ahern @ 2019-12-20  1:27 UTC (permalink / raw)
  To: Florian Westphal
  Cc: netfilter-devel, Martin Willi, David Ahern, Shrijeet Mukherjee,
	Roopa Prabhu, Benjamin Poirier

On 12/19/19 10:08 AM, Florian Westphal wrote:
> David Ahern <dsahern@gmail.com> wrote:
>> On 12/18/19 4:05 AM, Florian Westphal wrote:
>>> Allow to match on vrf slave ifindex or name.
>>>
>>> In case there was no slave interface involved, store 0 in the
>>> destination register just like existing iif/oif matching.
>>>
>>> sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
>>> as it depends on ip(6) stack parsing/storing info in skb->cb[].
>>>
>>> Cc: Martin Willi <martin@strongswan.org>
>>> Cc: David Ahern <dsahern@kernel.org>
>>> Cc: Shrijeet Mukherjee <shrijeet@gmail.com>
>>> Signed-off-by: Florian Westphal <fw@strlen.de>
>>> ---
>>>  include/uapi/linux/netfilter/nf_tables.h |  4 ++
>>>  net/netfilter/nft_meta.c                 | 76 +++++++++++++++++++++---
>>>  2 files changed, 73 insertions(+), 7 deletions(-)
>>>
>>
>> do you have an example that you can share?
> 
> nft add rule inet filter input meta sdifname "eth0" accept
> 
> so its similar to existing iif(name) that test for the input device.
> 
> This is the nft equivalent for the "slavedev" match that Martin proposed
> here:
> 
> http://patchwork.ozlabs.org/patch/1211435/
> 

Thanks for the example. I still have not found the time to get up to
speed with nft. I am glad to see netfilter matches on the enslaved
interface with VRF; it's a much needed feature.

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

* Re: [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching
  2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
                   ` (8 preceding siblings ...)
  2019-12-18 11:05 ` [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching Florian Westphal
@ 2019-12-26 16:42 ` Pablo Neira Ayuso
  9 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2019-12-26 16:42 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel

On Wed, Dec 18, 2019 at 12:05:12PM +0100, Florian Westphal wrote:
> Martin Willi recently proposed addition of new xt_slavedev module to
> allow matching the real interface within a VRF domain.
> 
> This adds an nft equivalent:
> 
> meta sdif "realdev" accept
> meta sdifname "realdev" accept
> 
> In case packet had no vrf slave, sdif stores 0 or "" name, just
> like 'oif/oifname' would on input.
> 
> sdif(name) is restricted to the ipv4/ipv6 input and forward hooks,
> as it depends on ip(6) stack parsing/storing info in skb->cb[].
> 
> Because meta main eval function is now exceeding more than 200 LOC,
> the first patches are diet work to debloat the function by using
> helpers where appropriate.
>
> Last patch adds the sdif/sdifname functionality.

Series applied, thanks Florian.

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

end of thread, other threads:[~2019-12-26 16:42 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-18 11:05 [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 1/9] netfilter: nft_meta: move time handling to helper Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 2/9] netfilter: nft_meta: move pkttype " Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 3/9] netfilter: nft_meta: move sk uid/git " Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 4/9] netfilter: nft_meta: move cgroup " Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 5/9] netfilter: nft_meta: move interface kind " Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 6/9] netfilter: nft_meta: move all interface related keys " Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 7/9] netfilter: nft_meta: place prandom handling in a helper Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 8/9] netfilter: nft_meta: place rtclassid " Florian Westphal
2019-12-18 11:05 ` [PATCH nf-next 9/9] netfilter: nft_meta: add support for slave device ifindex matching Florian Westphal
2019-12-19 16:46   ` David Ahern
2019-12-19 17:08     ` Florian Westphal
2019-12-20  1:27       ` David Ahern
2019-12-26 16:42 ` [PATCH nf-next 0/9] netfilter: nft_meta: add support for slave device matching Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).