netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org,
	razor@blackwall.org, jeremy@azazel.net
Subject: [PATCH net-next,v3 3/9] net: resolve forwarding path from virtual netdevice and HW destination address
Date: Wed, 11 Nov 2020 20:37:31 +0100	[thread overview]
Message-ID: <20201111193737.1793-4-pablo@netfilter.org> (raw)
In-Reply-To: <20201111193737.1793-1-pablo@netfilter.org>

This patch adds dev_fill_forward_path() which resolves the path to reach
the real netdevice from the IP forwarding side. This function takes as
input the netdevice and the destination hardware address and it walks
down the devices calling .ndo_fill_forward_path() for each device until
the real device is found.

For instance, assuming the following topology:

               IP forwarding
              /             \
           br0              eth0
           / \
       eth1  eth2
        .
        .
        .
       ethX
 ab:cd:ef:ab:cd:ef

where eth1 and eth2 are bridge ports and eth0 provides WAN connectivity.
ethX is the interface in another box which is connected to the eth1
bridge port.

For packets going through IP forwarding to br0 whose destination MAC
address is ab:cd:ef:ab:cd:ef, dev_fill_forward_path() provides the
following path:

	br0 -> eth1

.ndo_fill_forward_path for br0 looks up at the FDB for the bridge port
from the destination MAC address to get the bridge port eth1.

This information allows to create a fast path that bypasses the classic
bridge and IP forwarding paths, so packets go directly from the bridge
port eth1 to eth0 (wan interface) and vice versa.

             fast path
      .------------------------.
     /                          \
    |           IP forwarding   |
    |          /             \  \/
    |       br0               eth0
    .       / \
     -> eth1  eth2
        .
        .
        .
       ethX
 ab:cd:ef:ab:cd:ef

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netdevice.h | 27 +++++++++++++++++++++++++++
 net/core/dev.c            | 31 +++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7ce648a564f7..752649d8669f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -833,6 +833,27 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
 				       struct sk_buff *skb,
 				       struct net_device *sb_dev);
 
+enum net_device_path_type {
+	DEV_PATH_ETHERNET = 0,
+};
+
+struct net_device_path {
+	enum net_device_path_type	type;
+	const struct net_device		*dev;
+};
+
+#define NET_DEVICE_PATH_STACK_MAX	5
+
+struct net_device_path_stack {
+	int			num_paths;
+	struct net_device_path	path[NET_DEVICE_PATH_STACK_MAX];
+};
+
+struct net_device_path_ctx {
+	const struct net_device *dev;
+	const u8		*daddr;
+};
+
 enum tc_setup_type {
 	TC_SETUP_QDISC_MQPRIO,
 	TC_SETUP_CLSU32,
@@ -1279,6 +1300,8 @@ struct netdev_net_notifier {
  * struct net_device *(*ndo_get_peer_dev)(struct net_device *dev);
  *	If a device is paired with a peer device, return the peer instance.
  *	The caller must be under RCU read context.
+ * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path);
+ *	Get the forwarding path to reach the real device from the HW destination address
  */
 struct net_device_ops {
 	int			(*ndo_init)(struct net_device *dev);
@@ -1487,6 +1510,8 @@ struct net_device_ops {
 	int			(*ndo_tunnel_ctl)(struct net_device *dev,
 						  struct ip_tunnel_parm *p, int cmd);
 	struct net_device *	(*ndo_get_peer_dev)(struct net_device *dev);
+	int			(*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,
+							 struct net_device_path *path);
 };
 
 /**
@@ -2824,6 +2849,8 @@ void dev_remove_offload(struct packet_offload *po);
 
 int dev_get_iflink(const struct net_device *dev);
 int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+			  struct net_device_path_stack *stack);
 struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
 				      unsigned short mask);
 struct net_device *dev_get_by_name(struct net *net, const char *name);
diff --git a/net/core/dev.c b/net/core/dev.c
index 60d325bda0d7..854bdf41b5c1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -846,6 +846,37 @@ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
 
+int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+			  struct net_device_path_stack *stack)
+{
+	const struct net_device *last_dev;
+	struct net_device_path_ctx ctx;
+	struct net_device_path *path;
+	int ret = 0;
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.dev = dev;
+	ctx.daddr = daddr;
+
+	while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
+		last_dev = ctx.dev;
+
+		path = &stack->path[stack->num_paths++];
+		ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
+		if (ret < 0)
+			return -1;
+
+		if (WARN_ON_ONCE(last_dev == ctx.dev))
+			return -1;
+	}
+	path = &stack->path[stack->num_paths++];
+	path->type = DEV_PATH_ETHERNET;
+	path->dev = ctx.dev;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_fill_forward_path);
+
 /**
  *	__dev_get_by_name	- find a device by its name
  *	@net: the applicable net namespace
-- 
2.20.1


  parent reply	other threads:[~2020-11-11 19:38 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-11 19:37 [PATCH net-next,v3 0/9] netfilter: flowtable bridge and vlan enhancements Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 1/9] netfilter: flowtable: add hash offset field to tuple Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 2/9] netfilter: flowtable: add xmit path types Pablo Neira Ayuso
2020-11-11 19:37 ` Pablo Neira Ayuso [this message]
2020-11-14  1:42   ` [PATCH net-next,v3 3/9] net: resolve forwarding path from virtual netdevice and HW destination address Jakub Kicinski
2020-11-14 12:00     ` Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 4/9] net: 8021q: resolve forwarding path for vlan devices Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 5/9] bridge: resolve forwarding path for bridge devices Pablo Neira Ayuso
2020-11-12  0:53   ` Nikolay Aleksandrov
2020-11-13 15:40     ` Nikolay Aleksandrov
2020-11-11 19:37 ` [PATCH net-next,v3 6/9] netfilter: flowtable: use dev_fill_forward_path() to obtain ingress device Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 7/9] netfilter: flowtable: use dev_fill_forward_path() to obtain egress device Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 8/9] netfilter: flowtable: add vlan support Pablo Neira Ayuso
2020-11-11 19:37 ` [PATCH net-next,v3 9/9] selftests: netfilter: flowtable bridge and VLAN support Pablo Neira Ayuso
2020-11-14  1:55 ` [PATCH net-next,v3 0/9] netfilter: flowtable bridge and vlan enhancements Jakub Kicinski
2020-11-14 11:59   ` Pablo Neira Ayuso
2020-11-14 14:00     ` Tobias Waldekranz
2020-11-14 17:03       ` Jakub Kicinski
2020-11-16 22:18         ` Pablo Neira Ayuso
2020-11-16 22:28           ` Jakub Kicinski
2020-11-16 22:36             ` Pablo Neira Ayuso
2020-11-16 22:45               ` Jakub Kicinski
2020-11-16 22:56                 ` Pablo Neira Ayuso
2020-11-21 12:31                   ` Pablo Neira Ayuso
2020-11-21 18:15                     ` Jakub Kicinski
2020-11-21 18:56                       ` Pablo Neira Ayuso
2020-11-21 19:23                         ` Jakub Kicinski
2020-11-22 11:33                           ` Pablo Neira Ayuso
2020-11-16 22:31       ` Pablo Neira Ayuso

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=20201111193737.1793-4-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=jeremy@azazel.net \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=razor@blackwall.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is 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).