aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r--drivers/net/macvlan.c83
1 files changed, 72 insertions, 11 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 025367a94add..66a9bfe7b1c8 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -57,7 +57,7 @@ static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
57 struct hlist_node *n; 57 struct hlist_node *n;
58 58
59 hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) { 59 hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) {
60 if (!compare_ether_addr_64bits(vlan->dev->dev_addr, addr)) 60 if (ether_addr_equal_64bits(vlan->dev->dev_addr, addr))
61 return vlan; 61 return vlan;
62 } 62 }
63 return NULL; 63 return NULL;
@@ -96,7 +96,7 @@ static int macvlan_addr_busy(const struct macvlan_port *port,
96 * currently in use by the underlying device or 96 * currently in use by the underlying device or
97 * another macvlan. 97 * another macvlan.
98 */ 98 */
99 if (!compare_ether_addr_64bits(port->dev->dev_addr, addr)) 99 if (ether_addr_equal_64bits(port->dev->dev_addr, addr))
100 return 1; 100 return 1;
101 101
102 if (macvlan_hash_lookup(port, addr)) 102 if (macvlan_hash_lookup(port, addr))
@@ -118,8 +118,7 @@ static int macvlan_broadcast_one(struct sk_buff *skb,
118 return vlan->forward(dev, skb); 118 return vlan->forward(dev, skb);
119 119
120 skb->dev = dev; 120 skb->dev = dev;
121 if (!compare_ether_addr_64bits(eth->h_dest, 121 if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
122 dev->broadcast))
123 skb->pkt_type = PACKET_BROADCAST; 122 skb->pkt_type = PACKET_BROADCAST;
124 else 123 else
125 skb->pkt_type = PACKET_MULTICAST; 124 skb->pkt_type = PACKET_MULTICAST;
@@ -312,7 +311,8 @@ static int macvlan_open(struct net_device *dev)
312 int err; 311 int err;
313 312
314 if (vlan->port->passthru) { 313 if (vlan->port->passthru) {
315 dev_set_promiscuity(lowerdev, 1); 314 if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
315 dev_set_promiscuity(lowerdev, 1);
316 goto hash_add; 316 goto hash_add;
317 } 317 }
318 318
@@ -344,12 +344,15 @@ static int macvlan_stop(struct net_device *dev)
344 struct macvlan_dev *vlan = netdev_priv(dev); 344 struct macvlan_dev *vlan = netdev_priv(dev);
345 struct net_device *lowerdev = vlan->lowerdev; 345 struct net_device *lowerdev = vlan->lowerdev;
346 346
347 dev_uc_unsync(lowerdev, dev);
348 dev_mc_unsync(lowerdev, dev);
349
347 if (vlan->port->passthru) { 350 if (vlan->port->passthru) {
348 dev_set_promiscuity(lowerdev, -1); 351 if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
352 dev_set_promiscuity(lowerdev, -1);
349 goto hash_del; 353 goto hash_del;
350 } 354 }
351 355
352 dev_mc_unsync(lowerdev, dev);
353 if (dev->flags & IFF_ALLMULTI) 356 if (dev->flags & IFF_ALLMULTI)
354 dev_set_allmulti(lowerdev, -1); 357 dev_set_allmulti(lowerdev, -1);
355 358
@@ -399,10 +402,11 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
399 dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1); 402 dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
400} 403}
401 404
402static void macvlan_set_multicast_list(struct net_device *dev) 405static void macvlan_set_mac_lists(struct net_device *dev)
403{ 406{
404 struct macvlan_dev *vlan = netdev_priv(dev); 407 struct macvlan_dev *vlan = netdev_priv(dev);
405 408
409 dev_uc_sync(vlan->lowerdev, dev);
406 dev_mc_sync(vlan->lowerdev, dev); 410 dev_mc_sync(vlan->lowerdev, dev);
407} 411}
408 412
@@ -542,6 +546,43 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
542 return 0; 546 return 0;
543} 547}
544 548
549static int macvlan_fdb_add(struct ndmsg *ndm,
550 struct net_device *dev,
551 unsigned char *addr,
552 u16 flags)
553{
554 struct macvlan_dev *vlan = netdev_priv(dev);
555 int err = -EINVAL;
556
557 if (!vlan->port->passthru)
558 return -EOPNOTSUPP;
559
560 if (is_unicast_ether_addr(addr))
561 err = dev_uc_add_excl(dev, addr);
562 else if (is_multicast_ether_addr(addr))
563 err = dev_mc_add_excl(dev, addr);
564
565 return err;
566}
567
568static int macvlan_fdb_del(struct ndmsg *ndm,
569 struct net_device *dev,
570 unsigned char *addr)
571{
572 struct macvlan_dev *vlan = netdev_priv(dev);
573 int err = -EINVAL;
574
575 if (!vlan->port->passthru)
576 return -EOPNOTSUPP;
577
578 if (is_unicast_ether_addr(addr))
579 err = dev_uc_del(dev, addr);
580 else if (is_multicast_ether_addr(addr))
581 err = dev_mc_del(dev, addr);
582
583 return err;
584}
585
545static void macvlan_ethtool_get_drvinfo(struct net_device *dev, 586static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
546 struct ethtool_drvinfo *drvinfo) 587 struct ethtool_drvinfo *drvinfo)
547{ 588{
@@ -572,11 +613,14 @@ static const struct net_device_ops macvlan_netdev_ops = {
572 .ndo_change_mtu = macvlan_change_mtu, 613 .ndo_change_mtu = macvlan_change_mtu,
573 .ndo_change_rx_flags = macvlan_change_rx_flags, 614 .ndo_change_rx_flags = macvlan_change_rx_flags,
574 .ndo_set_mac_address = macvlan_set_mac_address, 615 .ndo_set_mac_address = macvlan_set_mac_address,
575 .ndo_set_rx_mode = macvlan_set_multicast_list, 616 .ndo_set_rx_mode = macvlan_set_mac_lists,
576 .ndo_get_stats64 = macvlan_dev_get_stats64, 617 .ndo_get_stats64 = macvlan_dev_get_stats64,
577 .ndo_validate_addr = eth_validate_addr, 618 .ndo_validate_addr = eth_validate_addr,
578 .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid, 619 .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid,
579 .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid, 620 .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid,
621 .ndo_fdb_add = macvlan_fdb_add,
622 .ndo_fdb_del = macvlan_fdb_del,
623 .ndo_fdb_dump = ndo_dflt_fdb_dump,
580}; 624};
581 625
582void macvlan_common_setup(struct net_device *dev) 626void macvlan_common_setup(struct net_device *dev)
@@ -711,6 +755,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
711 if (data && data[IFLA_MACVLAN_MODE]) 755 if (data && data[IFLA_MACVLAN_MODE])
712 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); 756 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
713 757
758 if (data && data[IFLA_MACVLAN_FLAGS])
759 vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
760
714 if (vlan->mode == MACVLAN_MODE_PASSTHRU) { 761 if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
715 if (port->count) 762 if (port->count)
716 return -EINVAL; 763 return -EINVAL;
@@ -760,6 +807,16 @@ static int macvlan_changelink(struct net_device *dev,
760 struct macvlan_dev *vlan = netdev_priv(dev); 807 struct macvlan_dev *vlan = netdev_priv(dev);
761 if (data && data[IFLA_MACVLAN_MODE]) 808 if (data && data[IFLA_MACVLAN_MODE])
762 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]); 809 vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
810 if (data && data[IFLA_MACVLAN_FLAGS]) {
811 __u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
812 bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC;
813
814 if (promisc && (flags & MACVLAN_FLAG_NOPROMISC))
815 dev_set_promiscuity(vlan->lowerdev, -1);
816 else if (promisc && !(flags & MACVLAN_FLAG_NOPROMISC))
817 dev_set_promiscuity(vlan->lowerdev, 1);
818 vlan->flags = flags;
819 }
763 return 0; 820 return 0;
764} 821}
765 822
@@ -773,7 +830,10 @@ static int macvlan_fill_info(struct sk_buff *skb,
773{ 830{
774 struct macvlan_dev *vlan = netdev_priv(dev); 831 struct macvlan_dev *vlan = netdev_priv(dev);
775 832
776 NLA_PUT_U32(skb, IFLA_MACVLAN_MODE, vlan->mode); 833 if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode))
834 goto nla_put_failure;
835 if (nla_put_u16(skb, IFLA_MACVLAN_FLAGS, vlan->flags))
836 goto nla_put_failure;
777 return 0; 837 return 0;
778 838
779nla_put_failure: 839nla_put_failure:
@@ -781,7 +841,8 @@ nla_put_failure:
781} 841}
782 842
783static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = { 843static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
784 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 }, 844 [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
845 [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
785}; 846};
786 847
787int macvlan_link_register(struct rtnl_link_ops *ops) 848int macvlan_link_register(struct rtnl_link_ops *ops)