aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWANG Cong <amwang@redhat.com>2010-05-06 03:48:51 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-06 03:48:51 -0400
commitf6dc31a85cd46a959bdd987adad14c3b645e03c1 (patch)
tree5e60aa95287daa0262e90f0db36e280dea163578
parentc06ee961d3c0e51009cbd0e123b61fbb97f37d0b (diff)
bonding: make bonding support netpoll
Based on Andy's work, but I modified a lot. Similar to the patch for bridge, this patch does: 1) implement the 2 methods to support netpoll for bonding; 2) modify netpoll during forwarding packets via bonding; 3) disable netpoll support of bonding when a netpoll-unabled device is added to bonding; 4) enable netpoll support when all underlying devices support netpoll. Cc: Andy Gospodarek <gospo@redhat.com> Cc: Jeff Moyer <jmoyer@redhat.com> Cc: Matt Mackall <mpm@selenic.com> Cc: Neil Horman <nhorman@tuxdriver.com> Cc: Jay Vosburgh <fubar@us.ibm.com> Cc: David Miller <davem@davemloft.net> Signed-off-by: WANG Cong <amwang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_main.c99
1 files changed, 98 insertions, 1 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 85e813c7762..5e12462a9d5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -59,6 +59,7 @@
59#include <linux/uaccess.h> 59#include <linux/uaccess.h>
60#include <linux/errno.h> 60#include <linux/errno.h>
61#include <linux/netdevice.h> 61#include <linux/netdevice.h>
62#include <linux/netpoll.h>
62#include <linux/inetdevice.h> 63#include <linux/inetdevice.h>
63#include <linux/igmp.h> 64#include <linux/igmp.h>
64#include <linux/etherdevice.h> 65#include <linux/etherdevice.h>
@@ -430,7 +431,18 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
430 } 431 }
431 432
432 skb->priority = 1; 433 skb->priority = 1;
433 dev_queue_xmit(skb); 434#ifdef CONFIG_NET_POLL_CONTROLLER
435 if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
436 struct netpoll *np = bond->dev->npinfo->netpoll;
437 slave_dev->npinfo = bond->dev->npinfo;
438 np->real_dev = np->dev = skb->dev;
439 slave_dev->priv_flags |= IFF_IN_NETPOLL;
440 netpoll_send_skb(np, skb);
441 slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
442 np->dev = bond->dev;
443 } else
444#endif
445 dev_queue_xmit(skb);
434 446
435 return 0; 447 return 0;
436} 448}
@@ -1256,6 +1268,61 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
1256 bond->slave_cnt--; 1268 bond->slave_cnt--;
1257} 1269}
1258 1270
1271#ifdef CONFIG_NET_POLL_CONTROLLER
1272/*
1273 * You must hold read lock on bond->lock before calling this.
1274 */
1275static bool slaves_support_netpoll(struct net_device *bond_dev)
1276{
1277 struct bonding *bond = netdev_priv(bond_dev);
1278 struct slave *slave;
1279 int i = 0;
1280 bool ret = true;
1281
1282 bond_for_each_slave(bond, slave, i) {
1283 if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL) ||
1284 !slave->dev->netdev_ops->ndo_poll_controller)
1285 ret = false;
1286 }
1287 return i != 0 && ret;
1288}
1289
1290static void bond_poll_controller(struct net_device *bond_dev)
1291{
1292 struct net_device *dev = bond_dev->npinfo->netpoll->real_dev;
1293 if (dev != bond_dev)
1294 netpoll_poll_dev(dev);
1295}
1296
1297static void bond_netpoll_cleanup(struct net_device *bond_dev)
1298{
1299 struct bonding *bond = netdev_priv(bond_dev);
1300 struct slave *slave;
1301 const struct net_device_ops *ops;
1302 int i;
1303
1304 read_lock(&bond->lock);
1305 bond_dev->npinfo = NULL;
1306 bond_for_each_slave(bond, slave, i) {
1307 if (slave->dev) {
1308 ops = slave->dev->netdev_ops;
1309 if (ops->ndo_netpoll_cleanup)
1310 ops->ndo_netpoll_cleanup(slave->dev);
1311 else
1312 slave->dev->npinfo = NULL;
1313 }
1314 }
1315 read_unlock(&bond->lock);
1316}
1317
1318#else
1319
1320static void bond_netpoll_cleanup(struct net_device *bond_dev)
1321{
1322}
1323
1324#endif
1325
1259/*---------------------------------- IOCTL ----------------------------------*/ 1326/*---------------------------------- IOCTL ----------------------------------*/
1260 1327
1261static int bond_sethwaddr(struct net_device *bond_dev, 1328static int bond_sethwaddr(struct net_device *bond_dev,
@@ -1674,6 +1741,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1674 1741
1675 bond_set_carrier(bond); 1742 bond_set_carrier(bond);
1676 1743
1744#ifdef CONFIG_NET_POLL_CONTROLLER
1745 if (slaves_support_netpoll(bond_dev)) {
1746 bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
1747 if (bond_dev->npinfo)
1748 slave_dev->npinfo = bond_dev->npinfo;
1749 } else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
1750 bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
1751 pr_info("New slave device %s does not support netpoll\n",
1752 slave_dev->name);
1753 pr_info("Disabling netpoll support for %s\n", bond_dev->name);
1754 }
1755#endif
1677 read_unlock(&bond->lock); 1756 read_unlock(&bond->lock);
1678 1757
1679 res = bond_create_slave_symlinks(bond_dev, slave_dev); 1758 res = bond_create_slave_symlinks(bond_dev, slave_dev);
@@ -1740,6 +1819,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
1740 return -EINVAL; 1819 return -EINVAL;
1741 } 1820 }
1742 1821
1822 netdev_bonding_change(bond_dev, NETDEV_BONDING_DESLAVE);
1743 write_lock_bh(&bond->lock); 1823 write_lock_bh(&bond->lock);
1744 1824
1745 slave = bond_get_slave_by_dev(bond, slave_dev); 1825 slave = bond_get_slave_by_dev(bond, slave_dev);
@@ -1868,6 +1948,17 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
1868 1948
1869 netdev_set_master(slave_dev, NULL); 1949 netdev_set_master(slave_dev, NULL);
1870 1950
1951#ifdef CONFIG_NET_POLL_CONTROLLER
1952 read_lock_bh(&bond->lock);
1953 if (slaves_support_netpoll(bond_dev))
1954 bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
1955 read_unlock_bh(&bond->lock);
1956 if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
1957 slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
1958 else
1959 slave_dev->npinfo = NULL;
1960#endif
1961
1871 /* close slave before restoring its mac address */ 1962 /* close slave before restoring its mac address */
1872 dev_close(slave_dev); 1963 dev_close(slave_dev);
1873 1964
@@ -4406,6 +4497,10 @@ static const struct net_device_ops bond_netdev_ops = {
4406 .ndo_vlan_rx_register = bond_vlan_rx_register, 4497 .ndo_vlan_rx_register = bond_vlan_rx_register,
4407 .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, 4498 .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
4408 .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, 4499 .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
4500#ifdef CONFIG_NET_POLL_CONTROLLER
4501 .ndo_netpoll_cleanup = bond_netpoll_cleanup,
4502 .ndo_poll_controller = bond_poll_controller,
4503#endif
4409}; 4504};
4410 4505
4411static void bond_destructor(struct net_device *bond_dev) 4506static void bond_destructor(struct net_device *bond_dev)
@@ -4499,6 +4594,8 @@ static void bond_uninit(struct net_device *bond_dev)
4499{ 4594{
4500 struct bonding *bond = netdev_priv(bond_dev); 4595 struct bonding *bond = netdev_priv(bond_dev);
4501 4596
4597 bond_netpoll_cleanup(bond_dev);
4598
4502 /* Release the bonded slaves */ 4599 /* Release the bonded slaves */
4503 bond_release_all(bond_dev); 4600 bond_release_all(bond_dev);
4504 4601