net: make bonding slaves honour master's skb->priority
[firefly-linux-kernel-4.4.55.git] / drivers / net / bonding / bond_main.c
index 43f2ea5410884ae34e5dd8db0fa2a25caea6d81c..c5944f1a4f9d52da7820337d8fb2324727724048 100644 (file)
@@ -395,7 +395,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
                        struct net_device *slave_dev)
 {
        skb->dev = slave_dev;
-       skb->priority = 1;
 
        skb->queue_mapping = bond_queue_mapping(skb);
 
@@ -557,7 +556,7 @@ down:
 static int bond_update_speed_duplex(struct slave *slave)
 {
        struct net_device *slave_dev = slave->dev;
-       struct ethtool_cmd etool = { .cmd = ETHTOOL_GSET };
+       struct ethtool_cmd ecmd;
        u32 slave_speed;
        int res;
 
@@ -565,18 +564,15 @@ static int bond_update_speed_duplex(struct slave *slave)
        slave->speed = SPEED_100;
        slave->duplex = DUPLEX_FULL;
 
-       if (!slave_dev->ethtool_ops || !slave_dev->ethtool_ops->get_settings)
-               return -1;
-
-       res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool);
+       res = __ethtool_get_settings(slave_dev, &ecmd);
        if (res < 0)
                return -1;
 
-       slave_speed = ethtool_cmd_speed(&etool);
+       slave_speed = ethtool_cmd_speed(&ecmd);
        if (slave_speed == 0 || slave_speed == ((__u32) -1))
                return -1;
 
-       switch (etool.duplex) {
+       switch (ecmd.duplex) {
        case DUPLEX_FULL:
        case DUPLEX_HALF:
                break;
@@ -585,7 +581,7 @@ static int bond_update_speed_duplex(struct slave *slave)
        }
 
        slave->speed = slave_speed;
-       slave->duplex = etool.duplex;
+       slave->duplex = ecmd.duplex;
 
        return 0;
 }
@@ -777,6 +773,9 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
 
        read_lock(&bond->lock);
 
+       if (bond->kill_timers)
+               goto out;
+
        /* rejoin all groups on bond device */
        __bond_resend_igmp_join_requests(bond->dev);
 
@@ -790,9 +789,9 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
                        __bond_resend_igmp_join_requests(vlan_dev);
        }
 
-       if (--bond->igmp_retrans > 0)
+       if ((--bond->igmp_retrans > 0) && !bond->kill_timers)
                queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5);
-
+out:
        read_unlock(&bond->lock);
 }
 
@@ -1432,6 +1431,8 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
        struct sk_buff *skb = *pskb;
        struct slave *slave;
        struct bonding *bond;
+       void (*recv_probe)(struct sk_buff *, struct bonding *,
+                               struct slave *);
 
        skb = skb_share_check(skb, GFP_ATOMIC);
        if (unlikely(!skb))
@@ -1445,11 +1446,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
        if (bond->params.arp_interval)
                slave->dev->last_rx = jiffies;
 
-       if (bond->recv_probe) {
+       recv_probe = ACCESS_ONCE(bond->recv_probe);
+       if (recv_probe) {
                struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
 
                if (likely(nskb)) {
-                       bond->recv_probe(nskb, bond, slave);
+                       recv_probe(nskb, bond, slave);
                        dev_kfree_skb(nskb);
                }
        }
@@ -2538,7 +2540,7 @@ void bond_mii_monitor(struct work_struct *work)
        }
 
 re_arm:
-       if (bond->params.miimon)
+       if (bond->params.miimon && !bond->kill_timers)
                queue_delayed_work(bond->wq, &bond->mii_work,
                                   msecs_to_jiffies(bond->params.miimon));
 out:
@@ -2886,7 +2888,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
        }
 
 re_arm:
-       if (bond->params.arp_interval)
+       if (bond->params.arp_interval && !bond->kill_timers)
                queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
 out:
        read_unlock(&bond->lock);
@@ -3154,7 +3156,7 @@ void bond_activebackup_arp_mon(struct work_struct *work)
        bond_ab_arp_probe(bond);
 
 re_arm:
-       if (bond->params.arp_interval)
+       if (bond->params.arp_interval && !bond->kill_timers)
                queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
 out:
        read_unlock(&bond->lock);
@@ -3704,44 +3706,27 @@ static bool bond_addr_in_mc_list(unsigned char *addr,
        return false;
 }
 
-static void bond_set_multicast_list(struct net_device *bond_dev)
+static void bond_change_rx_flags(struct net_device *bond_dev, int change)
 {
        struct bonding *bond = netdev_priv(bond_dev);
-       struct netdev_hw_addr *ha;
-       bool found;
-
-       /*
-        * Do promisc before checking multicast_mode
-        */
-       if ((bond_dev->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC))
-               /*
-                * FIXME: Need to handle the error when one of the multi-slaves
-                * encounters error.
-                */
-               bond_set_promiscuity(bond, 1);
-
 
-       if (!(bond_dev->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC))
-               bond_set_promiscuity(bond, -1);
+       if (change & IFF_PROMISC)
+               bond_set_promiscuity(bond,
+                                    bond_dev->flags & IFF_PROMISC ? 1 : -1);
 
+       if (change & IFF_ALLMULTI)
+               bond_set_allmulti(bond,
+                                 bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
 
-       /* set allmulti flag to slaves */
-       if ((bond_dev->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI))
-               /*
-                * FIXME: Need to handle the error when one of the multi-slaves
-                * encounters error.
-                */
-               bond_set_allmulti(bond, 1);
-
-
-       if (!(bond_dev->flags & IFF_ALLMULTI) && (bond->flags & IFF_ALLMULTI))
-               bond_set_allmulti(bond, -1);
-
+static void bond_set_multicast_list(struct net_device *bond_dev)
+{
+       struct bonding *bond = netdev_priv(bond_dev);
+       struct netdev_hw_addr *ha;
+       bool found;
 
        read_lock(&bond->lock);
 
-       bond->flags = bond_dev->flags;
-
        /* looking for addresses to add to slaves' mc list */
        netdev_for_each_mc_addr(ha, bond_dev) {
                found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
@@ -4300,7 +4285,8 @@ static const struct net_device_ops bond_netdev_ops = {
        .ndo_select_queue       = bond_select_queue,
        .ndo_get_stats64        = bond_get_stats,
        .ndo_do_ioctl           = bond_do_ioctl,
-       .ndo_set_multicast_list = bond_set_multicast_list,
+       .ndo_change_rx_flags    = bond_change_rx_flags,
+       .ndo_set_rx_mode        = bond_set_multicast_list,
        .ndo_change_mtu         = bond_change_mtu,
        .ndo_set_mac_address    = bond_set_mac_address,
        .ndo_neigh_setup        = bond_neigh_setup,
@@ -4846,11 +4832,20 @@ static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
        return 0;
 }
 
+static int bond_get_tx_queues(struct net *net, struct nlattr *tb[],
+                             unsigned int *num_queues,
+                             unsigned int *real_num_queues)
+{
+       *num_queues = tx_queues;
+       return 0;
+}
+
 static struct rtnl_link_ops bond_link_ops __read_mostly = {
        .kind           = "bond",
        .priv_size      = sizeof(struct bonding),
        .setup          = bond_setup,
        .validate       = bond_validate,
+       .get_tx_queues  = bond_get_tx_queues,
 };
 
 /* Create a new bond based on the specified name and bonding parameters.
@@ -4895,6 +4890,7 @@ static int __net_init bond_net_init(struct net *net)
        INIT_LIST_HEAD(&bn->dev_list);
 
        bond_create_proc_dir(bn);
+       bond_create_sysfs(bn);
        
        return 0;
 }
@@ -4903,6 +4899,7 @@ static void __net_exit bond_net_exit(struct net *net)
 {
        struct bond_net *bn = net_generic(net, bond_net_id);
 
+       bond_destroy_sysfs(bn);
        bond_destroy_proc_dir(bn);
 }
 
@@ -4940,10 +4937,6 @@ static int __init bonding_init(void)
                        goto err;
        }
 
-       res = bond_create_sysfs();
-       if (res)
-               goto err;
-
        register_netdevice_notifier(&bond_netdev_notifier);
        register_inetaddr_notifier(&bond_inetaddr_notifier);
 out:
@@ -4961,7 +4954,6 @@ static void __exit bonding_exit(void)
        unregister_netdevice_notifier(&bond_netdev_notifier);
        unregister_inetaddr_notifier(&bond_inetaddr_notifier);
 
-       bond_destroy_sysfs();
        bond_destroy_debugfs();
 
        rtnl_link_unregister(&bond_link_ops);