From e092c033d3f8a8de1cf369e8066fd8fe5edc901c Mon Sep 17 00:00:00 2001 From: Ravinder Konka Date: Fri, 18 Sep 2015 21:12:39 -0700 Subject: [PATCH] bridge: Add bridge API to access the bridge slave port This API is needed by the NSS connection manager modules to enable NSS fast path for bridge flows. The connection manager needs to inspect the netdevice of the bridge slave port that has learned a given MAC address. Currently no such API exists that is exported out of the kernel network stack for this purpose. Change-Id: I3f8848739d820346135b09b93f760122874468fd Signed-off-by: Ravinder konka Signed-off-by: Mohammed Javid --- include/linux/if_bridge.h | 5 +++++ net/bridge/br_if.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 9e57c4411734..6009f14c9cfc 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -52,6 +52,11 @@ struct br_ip_list { extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); +#ifdef CONFIG_ENABLE_SFE +extern struct net_device *br_port_dev_get(struct net_device *dev, + unsigned char *addr); +#endif + #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) int br_multicast_list_adjacent(struct net_device *dev, struct list_head *br_ip_list); diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4fe30b182ee7..ad682004ebb1 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -757,3 +757,36 @@ bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag) return p->flags & flag; } EXPORT_SYMBOL_GPL(br_port_flag_is_set); + +#ifdef CONFIG_ENABLE_SFE +/* br_port_dev_get() + * Using the given addr, identify the port to which it is reachable, + * returing a reference to the net device associated with that port. + * + * NOTE: Return NULL if given dev is not a bridge or + * the mac has no associated port + */ +struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr) +{ + struct net_bridge_fdb_entry *fdbe; + struct net_bridge *br; + struct net_device *netdev = NULL; + + /* Is this a bridge? */ + if (!(dev->priv_flags & IFF_EBRIDGE)) + return NULL; + + br = netdev_priv(dev); + + /* Lookup the fdb entry and get reference to the port dev */ + rcu_read_lock(); + fdbe = br_fdb_find_rcu(br, addr, 0); + if (fdbe && fdbe->dst) { + netdev = fdbe->dst->dev; /* port device */ + dev_hold(netdev); + } + rcu_read_unlock(); + return netdev; +} +EXPORT_SYMBOL(br_port_dev_get); +#endif