From patchwork Thu Feb 9 03:22:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Fastabend X-Patchwork-Id: 140309 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 88866B71A6 for ; Thu, 9 Feb 2012 14:33:55 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758014Ab2BIDdo (ORCPT ); Wed, 8 Feb 2012 22:33:44 -0500 Received: from mga09.intel.com ([134.134.136.24]:3801 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757896Ab2BIDdm (ORCPT ); Wed, 8 Feb 2012 22:33:42 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 08 Feb 2012 19:33:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.67,351,1309762800"; d="scan'208";a="107973624" Received: from unknown (HELO [127.0.0.1]) ([10.23.23.243]) by orsmga002.jf.intel.com with ESMTP; 08 Feb 2012 19:33:41 -0800 From: John Fastabend Subject: [RFC PATCH v0 1/2] net: bridge: propagate FDB table into hardware To: bhutchings@solarflare.com, roprabhu@cisco.com Cc: netdev@vger.kernel.org, mst@redhat.com, chrisw@redhat.com, davem@davemloft.net, gregory.v.rose@intel.com, shemminger@vyatta.com, kvm@vger.kernel.org, sri@us.ibm.com Date: Wed, 08 Feb 2012 19:22:06 -0800 Message-ID: <20120209032206.32468.92296.stgit@jf-dev1-dcblab> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Propagate software FDB table into hardware uc, mc lists when the NETIF_F_HW_FDB is set. This resolves the case below where an embedded switch is used in hardware to do inter-VF or VF-PF switching. This patch pushes the FDB entry (specifically the MAC address) into the embedded switch with dev_add_uc and dev_add_mc so the switch "learns" about the software bridge. veth0 veth2 | | ------------ | bridge0 | <---- software bridging ------------ / / ethx.y ethx VF PF \ \ <---- propagate FDB entries to HW \ \ -------------------- | Embedded Bridge | <---- hardware offloaded switching -------------------- This is only an RFC couple more changes are needed. (1) Optimize HW FDB set/del to only walk list if an FDB offloaded device is attached. Or decide it doesn't matter from unlikely() path. (2) Is it good enough to just call dev_uc_{add|del} or dev_mc_{add|del}? Or do some devices really need a new netdev callback to do this operation correctly. I think it should be good enough as is. (3) wrapped list walk in rcu_read_lock() just in case maybe every case is already inside rcu_read_lock()/unlock(). Also this is in response to this thread regarding the macvlan and exposing rx filters posting now to see if folks think this is the right idea and if it will resolve at least the bridge case. http://lists.openwall.net/netdev/2011/11/08/135 Signed-off-by: John Fastabend --- include/linux/netdev_features.h | 2 ++ net/bridge/br_fdb.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 0 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 77f5202..5936fae 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -55,6 +55,8 @@ enum { NETIF_F_NOCACHE_COPY_BIT, /* Use no-cache copyfromuser */ NETIF_F_LOOPBACK_BIT, /* Enable loopback */ + NETIF_F_HW_FDB, /* Hardware supports switching */ + /* * Add your fresh new feature above and remember to update * netdev_features_strings[] in net/core/ethtool.c and maybe diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 5ba0c84..4cc545b 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -81,9 +81,26 @@ static void fdb_rcu_free(struct rcu_head *head) kmem_cache_free(br_fdb_cache, ent); } +static void fdb_hw_delete(struct net_bridge *br, + struct net_bridge_fdb_entry *fdb) +{ + struct net_bridge_port *op; + + rcu_read_lock(); + list_for_each_entry_rcu(op, &br->port_list, list) { + struct net_device *dev = op->dev; + + if ((dev->features & NETIF_F_HW_FDB) && + dev != fdb->dst->dev) + dev_uc_del(dev, fdb->addr.addr); + } + rcu_read_unlock(); +} + static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) { hlist_del_rcu(&f->hlist); + fdb_hw_delete(br, f); fdb_notify(br, f, RTM_DELNEIGH); call_rcu(&f->rcu, fdb_rcu_free); } @@ -350,6 +367,22 @@ static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head, return NULL; } +static void fdb_hw_create(struct net_bridge *br, + struct net_bridge_fdb_entry *fdb) +{ + struct net_bridge_port *op; + + rcu_read_lock(); + list_for_each_entry_rcu(op, &br->port_list, list) { + struct net_device *dev = op->dev; + + if ((dev->features & NETIF_F_HW_FDB) && + dev != fdb->dst->dev) + dev_uc_add(dev, fdb->addr.addr); + } + rcu_read_unlock(); +} + static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, struct net_bridge_port *source, const unsigned char *addr) @@ -363,6 +396,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb->is_local = 0; fdb->is_static = 0; fdb->updated = fdb->used = jiffies; + fdb_hw_create(source->br, fdb); hlist_add_head_rcu(&fdb->hlist, head); } return fdb;