[RFC PATCH] macvlan: add FDB bridge ops
From: John Fastabend <hidden>
Date: 2012-03-21 00:40:20
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Add support to add/del and dump the forwarding database for macvlan passthru mode. The macvlan driver acts like a Two Port Mac Relay (TPMR 802.1Q-2011) in the passthru case so adding forwarding rules is just adding the addr to the uc or mc lists. By default the passthru mode puts the lowerdev into a promiscuous mode to receive all packets. This behavior is not changed by this patch. This is a bit problematic and needs to be solved without IMHO breaking existing mechanics. Maybe on the first add_fdb we can decrement the promisc mode? That seems to work reasonable well and keep existing functionality in place... but requires an initial add to set things up which is a bit annoying so maybe a flag is better. I haven't thought too hard about it yet so any ideas welcome This patch is a result of Roopa Prabhu's work. Follow up patches are needed for VEPA and VEB macvlan modes. Only lightly touch tested at this point. CC: Roopa Prabhu <redacted> Signed-off-by: John Fastabend <redacted> --- drivers/net/macvlan.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index f975afd..86af56b 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c@@ -349,6 +349,7 @@ static int macvlan_stop(struct net_device *dev) goto hash_del; } + dev_uc_unsync(lowerdev, dev); dev_mc_unsync(lowerdev, dev); if (dev->flags & IFF_ALLMULTI) dev_set_allmulti(lowerdev, -1);
@@ -403,6 +404,7 @@ static void macvlan_set_multicast_list(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); + dev_uc_sync(vlan->lowerdev, dev); dev_mc_sync(vlan->lowerdev, dev); }
@@ -542,6 +544,43 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev, return 0; } +static int macvlan_fdb_add(struct ndmsg *ndm, + struct net_device *dev, + unsigned char *addr, + u16 flags) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + int err = -EINVAL; + + if (!vlan->port->passthru) + return -EOPNOTSUPP; + + if (is_unicast_ether_addr(addr)) + err = dev_uc_add(dev, addr); + else if (is_multicast_ether_addr(addr)) + err = dev_mc_add(dev, addr); + + return err; +} + +static int macvlan_fdb_del(struct ndmsg *ndm, + struct net_device *dev, + unsigned char *addr) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + int err = -EINVAL; + + if (!vlan->port->passthru) + return -EOPNOTSUPP; + + if (is_unicast_ether_addr(addr)) + err = dev_uc_del(dev, addr); + else if (is_multicast_ether_addr(addr)) + err = dev_mc_del(dev, addr); + + return err; +} + static void macvlan_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) {
@@ -577,6 +616,9 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid, + .ndo_fdb_add = macvlan_fdb_add, + .ndo_fdb_del = macvlan_fdb_del, + .ndo_fdb_dump = ndo_dflt_fdb_dump, }; void macvlan_common_setup(struct net_device *dev)