summaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_3ad.c2
-rw-r--r--drivers/net/bonding/bond_alb.c12
-rw-r--r--drivers/net/bonding/bond_main.c100
-rw-r--r--drivers/net/bonding/bonding.h18
4 files changed, 51 insertions, 81 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 0ae0d7c54cc..793b0013827 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -660,7 +660,7 @@ static void __attach_bond_to_agg(struct port *port)
static void __detach_bond_from_agg(struct port *port)
{
port = NULL; /* just to satisfy the compiler */
- // This function does nothing sience the parser/multiplexer of the receive
+ // This function does nothing since the parser/multiplexer of the receive
// and the parser/multiplexer of the aggregator are already combined
}
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f820b26b9db..9abfde47931 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -180,11 +180,9 @@ static int tlb_initialize(struct bonding *bond)
int i;
new_hashtbl = kzalloc(size, GFP_KERNEL);
- if (!new_hashtbl) {
- pr_err("%s: Error: Failed to allocate TLB hash table\n",
- bond->dev->name);
+ if (!new_hashtbl)
return -1;
- }
+
_lock_tx_hashtbl_bh(bond);
bond_info->tx_hashtbl = new_hashtbl;
@@ -784,11 +782,9 @@ static int rlb_initialize(struct bonding *bond)
int i;
new_hashtbl = kmalloc(size, GFP_KERNEL);
- if (!new_hashtbl) {
- pr_err("%s: Error: Failed to allocate RLB hash table\n",
- bond->dev->name);
+ if (!new_hashtbl)
return -1;
- }
+
_lock_rx_hashtbl_bh(bond);
bond_info->rx_hashtbl = new_hashtbl;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 435984ad8b2..b920d829692 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -766,18 +766,30 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev)
*/
static void bond_resend_igmp_join_requests(struct bonding *bond)
{
- struct net_device *vlan_dev;
+ struct net_device *bond_dev, *vlan_dev, *master_dev;
struct vlan_entry *vlan;
read_lock(&bond->lock);
+ bond_dev = bond->dev;
+
/* rejoin all groups on bond device */
- __bond_resend_igmp_join_requests(bond->dev);
+ __bond_resend_igmp_join_requests(bond_dev);
+
+ /*
+ * if bond is enslaved to a bridge,
+ * then rejoin all groups on its master
+ */
+ master_dev = bond_dev->master;
+ if (master_dev)
+ if ((master_dev->priv_flags & IFF_EBRIDGE)
+ && (bond_dev->priv_flags & IFF_BRIDGE_PORT))
+ __bond_resend_igmp_join_requests(master_dev);
/* rejoin all groups on vlan devices */
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
rcu_read_lock();
- vlan_dev = __vlan_find_dev_deep(bond->dev,
+ vlan_dev = __vlan_find_dev_deep(bond_dev,
vlan->vlan_id);
rcu_read_unlock();
if (vlan_dev)
@@ -2561,12 +2573,16 @@ re_arm:
static int bond_has_this_ip(struct bonding *bond, __be32 ip)
{
struct vlan_entry *vlan;
+ struct net_device *vlan_dev;
- if (ip == bond->master_ip)
+ if (ip == bond_confirm_addr(bond->dev, 0, ip))
return 1;
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- if (ip == vlan->vlan_ip)
+ rcu_read_lock();
+ vlan_dev = __vlan_find_dev_deep(bond->dev, vlan->vlan_id);
+ rcu_read_unlock();
+ if (vlan_dev && ip == bond_confirm_addr(vlan_dev, 0, ip))
return 1;
}
@@ -2608,17 +2624,19 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
int i, vlan_id;
__be32 *targets = bond->params.arp_targets;
struct vlan_entry *vlan;
- struct net_device *vlan_dev;
+ struct net_device *vlan_dev = NULL;
struct rtable *rt;
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+ __be32 addr;
if (!targets[i])
break;
pr_debug("basa: target %x\n", targets[i]);
if (!bond_vlan_used(bond)) {
pr_debug("basa: empty vlan: arp_send\n");
+ addr = bond_confirm_addr(bond->dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- bond->master_ip, 0);
+ addr, 0);
continue;
}
@@ -2643,8 +2661,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (rt->dst.dev == bond->dev) {
ip_rt_put(rt);
pr_debug("basa: rtdev == bond->dev: arp_send\n");
+ addr = bond_confirm_addr(bond->dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- bond->master_ip, 0);
+ addr, 0);
continue;
}
@@ -2662,10 +2681,11 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
}
}
- if (vlan_id) {
+ if (vlan_id && vlan_dev) {
ip_rt_put(rt);
+ addr = bond_confirm_addr(vlan_dev, targets[i], 0);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
- vlan->vlan_ip, vlan_id);
+ addr, vlan_id);
continue;
}
@@ -3287,68 +3307,10 @@ static int bond_netdev_event(struct notifier_block *this,
return NOTIFY_DONE;
}
-/*
- * bond_inetaddr_event: handle inetaddr notifier chain events.
- *
- * We keep track of device IPs primarily to use as source addresses in
- * ARP monitor probes (rather than spewing out broadcasts all the time).
- *
- * We track one IP for the main device (if it has one), plus one per VLAN.
- */
-static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
- struct in_ifaddr *ifa = ptr;
- struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev;
- struct bond_net *bn = net_generic(dev_net(event_dev), bond_net_id);
- struct bonding *bond;
- struct vlan_entry *vlan;
-
- /* we only care about primary address */
- if(ifa->ifa_flags & IFA_F_SECONDARY)
- return NOTIFY_DONE;
-
- list_for_each_entry(bond, &bn->dev_list, bond_list) {
- if (bond->dev == event_dev) {
- switch (event) {
- case NETDEV_UP:
- bond->master_ip = ifa->ifa_local;
- return NOTIFY_OK;
- case NETDEV_DOWN:
- bond->master_ip = 0;
- return NOTIFY_OK;
- default:
- return NOTIFY_DONE;
- }
- }
-
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- vlan_dev = __vlan_find_dev_deep(bond->dev,
- vlan->vlan_id);
- if (vlan_dev == event_dev) {
- switch (event) {
- case NETDEV_UP:
- vlan->vlan_ip = ifa->ifa_local;
- return NOTIFY_OK;
- case NETDEV_DOWN:
- vlan->vlan_ip = 0;
- return NOTIFY_OK;
- default:
- return NOTIFY_DONE;
- }
- }
- }
- }
- return NOTIFY_DONE;
-}
-
static struct notifier_block bond_netdev_notifier = {
.notifier_call = bond_netdev_event,
};
-static struct notifier_block bond_inetaddr_notifier = {
- .notifier_call = bond_inetaddr_event,
-};
-
/*---------------------------- Hashing Policies -----------------------------*/
/*
@@ -4917,7 +4879,6 @@ static int __init bonding_init(void)
}
register_netdevice_notifier(&bond_netdev_notifier);
- register_inetaddr_notifier(&bond_inetaddr_notifier);
out:
return res;
err:
@@ -4931,7 +4892,6 @@ err_link:
static void __exit bonding_exit(void)
{
unregister_netdevice_notifier(&bond_netdev_notifier);
- unregister_inetaddr_notifier(&bond_inetaddr_notifier);
bond_destroy_debugfs();
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 1aecc37e5b4..9f2bae6616d 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -21,6 +21,7 @@
#include <linux/cpumask.h>
#include <linux/in6.h>
#include <linux/netpoll.h>
+#include <linux/inetdevice.h>
#include "bond_3ad.h"
#include "bond_alb.h"
@@ -166,7 +167,6 @@ struct bond_parm_tbl {
struct vlan_entry {
struct list_head vlan_list;
- __be32 vlan_ip;
unsigned short vlan_id;
};
@@ -232,7 +232,6 @@ struct bonding {
struct list_head bond_list;
struct netdev_hw_addr_list mc_list;
int (*xmit_hash_policy)(struct sk_buff *, int);
- __be32 master_ip;
u16 rr_tx_counter;
struct ad_bond_info ad_info;
struct alb_bond_info alb_info;
@@ -378,6 +377,21 @@ static inline bool bond_is_slave_inactive(struct slave *slave)
return slave->inactive;
}
+static inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local)
+{
+ struct in_device *in_dev;
+ __be32 addr = 0;
+
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
+
+ if (in_dev)
+ addr = inet_confirm_addr(in_dev, dst, local, RT_SCOPE_HOST);
+
+ rcu_read_unlock();
+ return addr;
+}
+
struct bond_net;
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);