[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <720907692575488526f06edc2cf5c8f783777d4f.1643044381.git.lorenzo@kernel.org>
Date: Mon, 24 Jan 2022 18:20:15 +0100
From: Lorenzo Bianconi <lorenzo@...nel.org>
To: bpf@...r.kernel.org, netdev@...r.kernel.org
Cc: lorenzo.bianconi@...hat.com, davem@...emloft.net, kuba@...nel.org,
ast@...nel.org, daniel@...earbox.net, dsahern@...nel.org,
komachi.yoshiki@...il.com, brouer@...hat.com, toke@...hat.com,
memxor@...il.com, andrii.nakryiko@...il.com
Subject: [RFC bpf-next 1/2] net: bridge: add unstable br_fdb_find_port_from_ifindex helper
Similar to bpf_xdp_ct_lookup routine, introduce
br_fdb_find_port_from_ifindex unstable helper in order to accelerate
linux bridge with XDP. br_fdb_find_port_from_ifindex will perform a
lookup in the associated bridge fdb table and it will return the
output ifindex if the destination address is associated to a bridge
port or -ENODEV for BOM traffic or if lookup fails.
Signed-off-by: Lorenzo Bianconi <lorenzo@...nel.org>
---
net/bridge/br.c | 21 +++++++++++++
net/bridge/br_fdb.c | 67 +++++++++++++++++++++++++++++++++++------
net/bridge/br_private.h | 12 ++++++++
3 files changed, 91 insertions(+), 9 deletions(-)
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 1fac72cc617f..d2d1c2341d9c 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -16,6 +16,8 @@
#include <net/llc.h>
#include <net/stp.h>
#include <net/switchdev.h>
+#include <linux/btf.h>
+#include <linux/btf_ids.h>
#include "br_private.h"
@@ -365,6 +367,17 @@ static const struct stp_proto br_stp_proto = {
.rcv = br_stp_rcv,
};
+#if (IS_ENABLED(CONFIG_DEBUG_INFO_BTF) || IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES))
+BTF_SET_START(br_xdp_fdb_check_kfunc_ids)
+BTF_ID(func, br_fdb_find_port_from_ifindex)
+BTF_SET_END(br_xdp_fdb_check_kfunc_ids)
+
+static const struct btf_kfunc_id_set br_xdp_fdb_kfunc_set = {
+ .owner = THIS_MODULE,
+ .check_set = &br_xdp_fdb_check_kfunc_ids,
+};
+#endif
+
static int __init br_init(void)
{
int err;
@@ -417,6 +430,14 @@ static int __init br_init(void)
"need this.\n");
#endif
+#if (IS_ENABLED(CONFIG_DEBUG_INFO_BTF) || IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES))
+ err = register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &br_xdp_fdb_kfunc_set);
+ if (err < 0) {
+ br_netlink_fini();
+ goto err_out6;
+ }
+#endif
+
return 0;
err_out6:
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 6ccda68bd473..cd3afa240298 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -235,30 +235,79 @@ static struct net_bridge_fdb_entry *br_fdb_find(struct net_bridge *br,
return fdb;
}
-struct net_device *br_fdb_find_port(const struct net_device *br_dev,
- const unsigned char *addr,
- __u16 vid)
+static struct net_device *
+__br_fdb_find_port(const struct net_device *br_dev,
+ const unsigned char *addr,
+ __u16 vid, bool ts_update)
{
struct net_bridge_fdb_entry *f;
- struct net_device *dev = NULL;
struct net_bridge *br;
- ASSERT_RTNL();
-
if (!netif_is_bridge_master(br_dev))
return NULL;
br = netdev_priv(br_dev);
- rcu_read_lock();
f = br_fdb_find_rcu(br, addr, vid);
- if (f && f->dst)
- dev = f->dst->dev;
+
+ if (f && f->dst) {
+ f->updated = jiffies;
+ f->used = f->updated;
+ return f->dst->dev;
+ }
+ return NULL;
+}
+
+struct net_device *br_fdb_find_port(const struct net_device *br_dev,
+ const unsigned char *addr,
+ __u16 vid)
+{
+ struct net_device *dev;
+
+ ASSERT_RTNL();
+
+ rcu_read_lock();
+ dev = __br_fdb_find_port(br_dev, addr, vid, false);
rcu_read_unlock();
return dev;
}
EXPORT_SYMBOL_GPL(br_fdb_find_port);
+int br_fdb_find_port_from_ifindex(struct xdp_md *xdp_ctx,
+ struct bpf_fdb_lookup *opt,
+ u32 opt__sz)
+{
+ struct xdp_buff *ctx = (struct xdp_buff *)xdp_ctx;
+ struct net_bridge_port *port;
+ struct net_device *dev;
+ int ret = -ENODEV;
+
+ BUILD_BUG_ON(sizeof(struct bpf_fdb_lookup) != NF_BPF_FDB_OPTS_SZ);
+ if (!opt || opt__sz != sizeof(struct bpf_fdb_lookup))
+ return -ENODEV;
+
+ rcu_read_lock();
+
+ dev = dev_get_by_index_rcu(dev_net(ctx->rxq->dev), opt->ifindex);
+ if (!dev)
+ goto out;
+
+ if (unlikely(!netif_is_bridge_port(dev)))
+ goto out;
+
+ port = br_port_get_check_rcu(dev);
+ if (unlikely(!port || !port->br))
+ goto out;
+
+ dev = __br_fdb_find_port(port->br->dev, opt->addr, opt->vid, true);
+ if (dev)
+ ret = dev->ifindex;
+out:
+ rcu_read_unlock();
+
+ return ret;
+}
+
struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br,
const unsigned char *addr,
__u16 vid)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2661dda1a92b..64d4f1727da2 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -18,6 +18,7 @@
#include <linux/if_vlan.h>
#include <linux/rhashtable.h>
#include <linux/refcount.h>
+#include <linux/bpf.h>
#define BR_HASH_BITS 8
#define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -2094,4 +2095,15 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
+
+#define NF_BPF_FDB_OPTS_SZ 12
+struct bpf_fdb_lookup {
+ u8 addr[ETH_ALEN]; /* ETH_ALEN */
+ u16 vid;
+ u32 ifindex;
+};
+
+int br_fdb_find_port_from_ifindex(struct xdp_md *xdp_ctx,
+ struct bpf_fdb_lookup *opt,
+ u32 opt__sz);
#endif
--
2.34.1
Powered by blists - more mailing lists