aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2020-10-24 21:14:16 +0200
committerFelix Fietkau <nbd@nbd.name>2021-02-16 20:06:51 +0100
commitb10d6044599d8c1fa7fbb2374bcbf30118d39db1 (patch)
tree3fc84f92c14dfa7178487b71e1b8d63c2b688439 /target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch
parent299b8554183791b325e393c880d32360d7d72f73 (diff)
downloadupstream-b10d6044599d8c1fa7fbb2374bcbf30118d39db1.tar.gz
upstream-b10d6044599d8c1fa7fbb2374bcbf30118d39db1.tar.bz2
upstream-b10d6044599d8c1fa7fbb2374bcbf30118d39db1.zip
kernel: add linux 5.10 support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch')
-rw-r--r--target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch170
1 files changed, 170 insertions, 0 deletions
diff --git a/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch b/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch
new file mode 100644
index 0000000000..953446baab
--- /dev/null
+++ b/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch
@@ -0,0 +1,170 @@
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Sun, 10 Jan 2021 15:53:58 +0100
+Subject: [PATCH] net: resolve forwarding path from virtual netdevice and
+ HW destination address
+
+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>
+---
+
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -833,6 +833,27 @@ typedef u16 (*select_queue_fallback_t)(s
+ 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);
+ };
+
+ /**
+@@ -2798,6 +2823,8 @@ void dev_remove_offload(struct packet_of
+
+ 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);
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -846,6 +846,52 @@ int dev_fill_metadata_dst(struct net_dev
+ }
+ EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
+
++static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
++{
++ int k = stack->num_paths++;
++
++ if (WARN_ON_ONCE(k >= NET_DEVICE_PATH_STACK_MAX))
++ return NULL;
++
++ return &stack->path[k];
++}
++
++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 = {
++ .dev = dev,
++ .daddr = daddr,
++ };
++ struct net_device_path *path;
++ int ret = 0;
++
++ stack->num_paths = 0;
++ while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
++ last_dev = ctx.dev;
++ path = dev_fwd_path(stack);
++ if (!path)
++ return -1;
++
++ memset(path, 0, sizeof(struct net_device_path));
++ 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 = dev_fwd_path(stack);
++ if (!path)
++ return -1;
++ 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