aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvlan.c
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2012-04-15 02:44:37 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-15 13:06:05 -0400
commitdf8ef8f3aaa6692970a436204c4429210addb23a (patch)
treee214674aeafc01e140cc9d2eb24e5d6fb37b422a /drivers/net/macvlan.c
parent2b2027124ff1bc420d4a86e37a57feae5e356d2d (diff)
macvlan: add FDB bridge ops and macvlan flags
This adds FDB bridge ops to the macvlan device passthru mode. Additionally a flags field was added and a NOPROMISC bit to allow users to use passthru mode without the driver calling dev_set_promiscuity(). The flags field is a u16 placed in a 4 byte hole (consuming 2 bytes) of the macvlan_dev struct. We want to do this so that the macvlan driver or stack above the macvlan driver does not have to process every packet. For the use case where we know all the MAC addresses of the endstations above us this works well. This patch is a result of Roopa Prabhu's work. Follow up patches are needed for VEPA and VEB macvlan modes. v2: Change from distinct nopromisc mode to a flags field to configure this. This avoids the tendency to add a new mode every time we need some slightly different behavior. v3: fix error in dev_set_promiscuity and add change and get link attributes for flags. CC: Roopa Prabhu <roprabhu@cisco.com> CC: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r--drivers/net/macvlan.c73
1 files changed, 67 insertions, 6 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b17fc9007099..9653ed6998fe 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -312,7 +312,8 @@ static int macvlan_open(struct net_device *dev)
312 int err; 312 int err;
313 313
314 if (vlan->port->passthru) { 314 if (vlan->port->passthru) {
315 dev_set_promiscuity(lowerdev, 1); 315 if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
316 dev_set_promiscuity(lowerdev, 1);
316 goto hash_add; 317 goto hash_add;
317 } 318 }
318 319
@@ -344,12 +345,15 @@ static int macvlan_stop(struct net_device *dev)
344 struct macvlan_dev *vlan = netdev_priv(dev); 345 struct macvlan_dev *vlan = netdev_priv(dev);
345 struct net_device *lowerdev = vlan->lowerdev; 346 struct net_device *lowerdev = vlan->lowerdev;
346 347
348 dev_uc_unsync(lowerdev, dev);
349 dev_mc_unsync(lowerdev, dev);
350
347 if (vlan->port->passthru) { 351 if (vlan->port->passthru) {
348 dev_set_promiscuity(lowerdev, -1); 352 if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
353 dev_set_promiscuity(lowerdev, -1);
349 goto hash_del; 354 goto hash_del;
350 } 355 }
351 356
352 dev_mc_unsync(lowerdev, dev);
353 if (dev->flags & IFF_ALLMULTI) 357 if (dev->flags & IFF_ALLMULTI)
354 dev_set_allmulti(lowerdev, -1); 358 dev_set_allmulti(lowerdev, -1);
355 359
@@ -399,10 +403,11 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
399 dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1); 403 dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
400} 404}
401 405
402static void macvlan_set_multicast_list(struct net_device *dev) 406static void macvlan_set_mac_lists(struct net_device *dev)
403{ 407{
404 struct macvlan_dev *vlan = netdev_priv(dev); 408 struct macvlan_dev *vlan = netdev_priv(dev);
405 409
410 dev_uc_sync(vlan->lowerdev, dev);
406 dev_mc_sync(vlan->lowerdev, dev); 411 dev_mc_sync(vlan->lowerdev, dev);
407} 412}
408 413
@@ -542,6 +547,43 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
542 return 0; 547 return 0;
543} 548}
544 549
550static int macvlan_fdb_add(struct ndmsg *ndm,
551 struct net_device *dev,
552 unsigned char *addr,
553 u16 flags)
554{
555 struct macvlan_dev *vlan = netdev_priv(dev);
556 int err = -EINVAL;
557
558 if (!vlan->port->passthru)
559 return -EOPNOTSUPP;
560
561 if (is_unicast_ether_addr(addr))
562 err = dev_uc_add_excl(dev, addr);
563 else if (is_multicast_ether_addr(addr))
564 err = dev_mc_add_excl(dev, addr);
565
566 return err;
567}
568
569static int macvlan_fdb_del(struct ndmsg *ndm,
570 struct net_device *dev,
571 unsigned char *addr)
572{
573 struct macvlan_dev *vlan = netdev_priv(dev);
574 int err = -EINVAL;
575
576 if (!vlan->port->passthru)
577 return -EOPNOTSUPP;
578
579 if (is_unicast_ether_addr(addr))
580 err = dev_uc_del(dev, addr);
581 else if (is_multicast_ether_addr(addr))
582 err = dev_mc_del(dev, addr);
583
584 return err;
585}
586
545static void macvlan_ethtool_get_drvinfo(struct net_device *dev, 587static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
546 struct ethtool_drvinfo *drvinfo) 588 struct ethtool_drvinfo *drvinfo)
547{ 589{
@@ -572,11 +614,14 @@ static const struct net_device_ops macvlan_netdev_ops = {
572 .ndo_change_mtu = macvlan_change_mtu, 614 .ndo_change_mtu = macvlan_change_mtu,
573 .ndo_change_rx_flags = macvlan_change_rx_flags, 615 .ndo_change_rx_flags = macvlan_change_rx_flags,
574 .ndo_set_mac_address = macvlan_set_mac_address, 616 .ndo_set_mac_address = macvlan_set_mac_address,
575 .ndo_set_rx_mode = macvlan_set_multicast_list, 617 .ndo_set_rx_mode = macvlan_set_mac_lists,
576 .ndo_get_stats64 = macvlan_dev_get_stats64, 618 .ndo_get_stats64 = macvlan_dev_get_stats64,
577 .ndo_validate_addr = eth_validate_addr, 619 .ndo_validate_addr = eth_validate_addr,
578 .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid, 620 .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid,
579 .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid, 621 .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid,
622 .ndo_fdb_add = macvlan_fdb_add,
623 .ndo_fdb_del = macvlan_fdb_del,
624 .ndo_fdb_dump = ndo_dflt_fdb_dump,
580}; 625};
581 626
582void macvlan_common_setup(struct net_device *dev) 627void macvlan_common_setup(struct net_device *dev)
@@ -711,6 +756,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
711 if (data && data[IFLA_MACVLAN_MODE]) 756 if (data && data[IFLA_MACVLAN_MODE])
712 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); 757 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
713 758
759 if (data && data[IFLA_MACVLAN_FLAGS])
760 vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
761
714 if (vlan->mode == MACVLAN_MODE_PASSTHRU) { 762 if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
715 if (port->count) 763 if (port->count)
716 return -EINVAL; 764 return -EINVAL;
@@ -760,6 +808,16 @@ static int macvlan_changelink(struct net_device *dev,
760 struct macvlan_dev *vlan = netdev_priv(dev); 808 struct macvlan_dev *vlan = netdev_priv(dev);
761 if (data && data[IFLA_MACVLAN_MODE]) 809 if (data && data[IFLA_MACVLAN_MODE])
762 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); 810 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
811 if (data && data[IFLA_MACVLAN_FLAGS]) {
812 __u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
813 bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC;
814
815 if (promisc && (flags & MACVLAN_FLAG_NOPROMISC))
816 dev_set_promiscuity(vlan->lowerdev, -1);
817 else if (promisc && !(flags & MACVLAN_FLAG_NOPROMISC))
818 dev_set_promiscuity(vlan->lowerdev, 1);
819 vlan->flags = flags;
820 }
763 return 0; 821 return 0;
764} 822}
765 823
@@ -775,6 +833,8 @@ static int macvlan_fill_info(struct sk_buff *skb,
775 833
776 if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode)) 834 if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode))
777 goto nla_put_failure; 835 goto nla_put_failure;
836 if (nla_put_u16(skb, IFLA_MACVLAN_FLAGS, vlan->flags))
837 goto nla_put_failure;
778 return 0; 838 return 0;
779 839
780nla_put_failure: 840nla_put_failure:
@@ -782,7 +842,8 @@ nla_put_failure:
782} 842}
783 843
784static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { 844static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
785 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, 845 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
846 [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
786}; 847};
787 848
788int macvlan_link_register(struct rtnl_link_ops *ops) 849int macvlan_link_register(struct rtnl_link_ops *ops)