aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorBrian Haley <brian.haley@hp.com>2008-11-04 20:51:14 -0500
committerJeff Garzik <jgarzik@redhat.com>2008-11-06 00:49:37 -0500
commit305d552accae6afb859c493ebc7d98ca3371dae2 (patch)
treeaa1230b1a6cf85ceb36d3e8a8a155ef4348523b6 /drivers/net/bonding
parent61c9eaf90081cbe6dc4f389e0056bff76eca19ec (diff)
bonding: send IPv6 neighbor advertisement on failover
This patch adds better IPv6 failover support for bonding devices, especially when in active-backup mode and there are only IPv6 addresses configured, as reported by Alex Sidorenko. - Creates a new file, net/drivers/bonding/bond_ipv6.c, for the IPv6-specific routines. Both regular bonds and VLANs over bonds are supported. - Adds a new tunable, num_unsol_na, to limit the number of unsolicited IPv6 Neighbor Advertisements that are sent on a failover event. Default is 1. - Creates two new IPv6 neighbor discovery functions: ndisc_build_skb() ndisc_send_skb() These were required to support VLANs since we have to be able to add the VLAN id to the skb since ndisc_send_na() and friends shouldn't be asked to do this. These two routines are basically __ndisc_send() split into two pieces, in a slightly different order. - Updates Documentation/networking/bonding.txt and bumps the rev of bond support to 3.4.0. On failover, this new code will generate one packet: - An unsolicited IPv6 Neighbor Advertisement, which helps the switch learn that the address has moved to the new slave. Testing has shown that sending just the NA results in pretty good behavior when in active-back mode, I saw no lost ping packets for example. Signed-off-by: Brian Haley <brian.haley@hp.com> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/Makefile3
-rw-r--r--drivers/net/bonding/bond_ipv6.c218
-rw-r--r--drivers/net/bonding/bond_main.c33
-rw-r--r--drivers/net/bonding/bond_sysfs.c42
-rw-r--r--drivers/net/bonding/bonding.h34
5 files changed, 326 insertions, 4 deletions
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile
index 5cdae2bc055a..6f9c6faef24c 100644
--- a/drivers/net/bonding/Makefile
+++ b/drivers/net/bonding/Makefile
@@ -6,3 +6,6 @@ obj-$(CONFIG_BONDING) += bonding.o
6 6
7bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o 7bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
8 8
9ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
10bonding-objs += $(ipv6-y)
11
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
new file mode 100644
index 000000000000..7c78b7bf671c
--- /dev/null
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -0,0 +1,218 @@
1/*
2 * Copyright(c) 2008 Hewlett-Packard Development Company, L.P.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 */
22
23//#define BONDING_DEBUG 1
24
25#include <linux/types.h>
26#include <linux/if_vlan.h>
27#include <net/ipv6.h>
28#include <net/ndisc.h>
29#include <net/addrconf.h>
30#include "bonding.h"
31
32/*
33 * Assign bond->master_ipv6 to the next IPv6 address in the list, or
34 * zero it out if there are none.
35 */
36static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr)
37{
38 struct inet6_dev *idev;
39 struct inet6_ifaddr *ifa;
40
41 if (!dev)
42 return;
43
44 idev = in6_dev_get(dev);
45 if (!idev)
46 return;
47
48 read_lock_bh(&idev->lock);
49 ifa = idev->addr_list;
50 if (ifa)
51 ipv6_addr_copy(addr, &ifa->addr);
52 else
53 ipv6_addr_set(addr, 0, 0, 0, 0);
54
55 read_unlock_bh(&idev->lock);
56
57 in6_dev_put(idev);
58}
59
60static void bond_na_send(struct net_device *slave_dev,
61 struct in6_addr *daddr,
62 int router,
63 unsigned short vlan_id)
64{
65 struct in6_addr mcaddr;
66 struct icmp6hdr icmp6h = {
67 .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
68 };
69 struct sk_buff *skb;
70
71 icmp6h.icmp6_router = router;
72 icmp6h.icmp6_solicited = 0;
73 icmp6h.icmp6_override = 1;
74
75 addrconf_addr_solict_mult(daddr, &mcaddr);
76
77 dprintk("ipv6 na on slave %s: dest %pI6, src %pI6\n",
78 slave->name, &mcaddr, daddr);
79
80 skb = ndisc_build_skb(slave_dev, &mcaddr, daddr, &icmp6h, daddr,
81 ND_OPT_TARGET_LL_ADDR);
82
83 if (!skb) {
84 printk(KERN_ERR DRV_NAME ": NA packet allocation failed\n");
85 return;
86 }
87
88 if (vlan_id) {
89 skb = vlan_put_tag(skb, vlan_id);
90 if (!skb) {
91 printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
92 return;
93 }
94 }
95
96 ndisc_send_skb(skb, slave_dev, NULL, &mcaddr, daddr, &icmp6h);
97}
98
99/*
100 * Kick out an unsolicited Neighbor Advertisement for an IPv6 address on
101 * the bonding master. This will help the switch learn our address
102 * if in active-backup mode.
103 *
104 * Caller must hold curr_slave_lock for read or better
105 */
106void bond_send_unsolicited_na(struct bonding *bond)
107{
108 struct slave *slave = bond->curr_active_slave;
109 struct vlan_entry *vlan;
110 struct inet6_dev *idev;
111 int is_router;
112
113 dprintk("bond_send_unsol_na: bond %s slave %s\n", bond->dev->name,
114 slave ? slave->dev->name : "NULL");
115
116 if (!slave || !bond->send_unsol_na ||
117 test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
118 return;
119
120 bond->send_unsol_na--;
121
122 idev = in6_dev_get(bond->dev);
123 if (!idev)
124 return;
125
126 is_router = !!idev->cnf.forwarding;
127
128 in6_dev_put(idev);
129
130 if (!ipv6_addr_any(&bond->master_ipv6))
131 bond_na_send(slave->dev, &bond->master_ipv6, is_router, 0);
132
133 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
134 if (!ipv6_addr_any(&vlan->vlan_ipv6)) {
135 bond_na_send(slave->dev, &vlan->vlan_ipv6, is_router,
136 vlan->vlan_id);
137 }
138 }
139}
140
141/*
142 * bond_inet6addr_event: handle inet6addr notifier chain events.
143 *
144 * We keep track of device IPv6 addresses primarily to use as source
145 * addresses in NS probes.
146 *
147 * We track one IPv6 for the main device (if it has one).
148 */
149static int bond_inet6addr_event(struct notifier_block *this,
150 unsigned long event,
151 void *ptr)
152{
153 struct inet6_ifaddr *ifa = ptr;
154 struct net_device *vlan_dev, *event_dev = ifa->idev->dev;
155 struct bonding *bond;
156 struct vlan_entry *vlan;
157
158 if (dev_net(event_dev) != &init_net)
159 return NOTIFY_DONE;
160
161 list_for_each_entry(bond, &bond_dev_list, bond_list) {
162 if (bond->dev == event_dev) {
163 switch (event) {
164 case NETDEV_UP:
165 if (ipv6_addr_any(&bond->master_ipv6))
166 ipv6_addr_copy(&bond->master_ipv6,
167 &ifa->addr);
168 return NOTIFY_OK;
169 case NETDEV_DOWN:
170 if (ipv6_addr_equal(&bond->master_ipv6,
171 &ifa->addr))
172 bond_glean_dev_ipv6(bond->dev,
173 &bond->master_ipv6);
174 return NOTIFY_OK;
175 default:
176 return NOTIFY_DONE;
177 }
178 }
179
180 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
181 vlan_dev = vlan_group_get_device(bond->vlgrp,
182 vlan->vlan_id);
183 if (vlan_dev == event_dev) {
184 switch (event) {
185 case NETDEV_UP:
186 if (ipv6_addr_any(&vlan->vlan_ipv6))
187 ipv6_addr_copy(&vlan->vlan_ipv6,
188 &ifa->addr);
189 return NOTIFY_OK;
190 case NETDEV_DOWN:
191 if (ipv6_addr_equal(&vlan->vlan_ipv6,
192 &ifa->addr))
193 bond_glean_dev_ipv6(vlan_dev,
194 &vlan->vlan_ipv6);
195 return NOTIFY_OK;
196 default:
197 return NOTIFY_DONE;
198 }
199 }
200 }
201 }
202 return NOTIFY_DONE;
203}
204
205static struct notifier_block bond_inet6addr_notifier = {
206 .notifier_call = bond_inet6addr_event,
207};
208
209void bond_register_ipv6_notifier(void)
210{
211 register_inet6addr_notifier(&bond_inet6addr_notifier);
212}
213
214void bond_unregister_ipv6_notifier(void)
215{
216 unregister_inet6addr_notifier(&bond_inet6addr_notifier);
217}
218
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 39575d764974..798d98ce2d97 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -89,6 +89,7 @@
89 89
90static int max_bonds = BOND_DEFAULT_MAX_BONDS; 90static int max_bonds = BOND_DEFAULT_MAX_BONDS;
91static int num_grat_arp = 1; 91static int num_grat_arp = 1;
92static int num_unsol_na = 1;
92static int miimon = BOND_LINK_MON_INTERV; 93static int miimon = BOND_LINK_MON_INTERV;
93static int updelay = 0; 94static int updelay = 0;
94static int downdelay = 0; 95static int downdelay = 0;
@@ -107,6 +108,8 @@ module_param(max_bonds, int, 0);
107MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); 108MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
108module_param(num_grat_arp, int, 0644); 109module_param(num_grat_arp, int, 0644);
109MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event"); 110MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
111module_param(num_unsol_na, int, 0644);
112MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event");
110module_param(miimon, int, 0); 113module_param(miimon, int, 0);
111MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); 114MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
112module_param(updelay, int, 0); 115module_param(updelay, int, 0);
@@ -242,14 +245,13 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
242 dprintk("bond: %s, vlan id %d\n", 245 dprintk("bond: %s, vlan id %d\n",
243 (bond ? bond->dev->name: "None"), vlan_id); 246 (bond ? bond->dev->name: "None"), vlan_id);
244 247
245 vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL); 248 vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL);
246 if (!vlan) { 249 if (!vlan) {
247 return -ENOMEM; 250 return -ENOMEM;
248 } 251 }
249 252
250 INIT_LIST_HEAD(&vlan->vlan_list); 253 INIT_LIST_HEAD(&vlan->vlan_list);
251 vlan->vlan_id = vlan_id; 254 vlan->vlan_id = vlan_id;
252 vlan->vlan_ip = 0;
253 255
254 write_lock_bh(&bond->lock); 256 write_lock_bh(&bond->lock);
255 257
@@ -1208,6 +1210,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
1208 bond->send_grat_arp = bond->params.num_grat_arp; 1210 bond->send_grat_arp = bond->params.num_grat_arp;
1209 bond_send_gratuitous_arp(bond); 1211 bond_send_gratuitous_arp(bond);
1210 1212
1213 bond->send_unsol_na = bond->params.num_unsol_na;
1214 bond_send_unsolicited_na(bond);
1215
1211 write_unlock_bh(&bond->curr_slave_lock); 1216 write_unlock_bh(&bond->curr_slave_lock);
1212 read_unlock(&bond->lock); 1217 read_unlock(&bond->lock);
1213 1218
@@ -2463,6 +2468,12 @@ void bond_mii_monitor(struct work_struct *work)
2463 read_unlock(&bond->curr_slave_lock); 2468 read_unlock(&bond->curr_slave_lock);
2464 } 2469 }
2465 2470
2471 if (bond->send_unsol_na) {
2472 read_lock(&bond->curr_slave_lock);
2473 bond_send_unsolicited_na(bond);
2474 read_unlock(&bond->curr_slave_lock);
2475 }
2476
2466 if (bond_miimon_inspect(bond)) { 2477 if (bond_miimon_inspect(bond)) {
2467 read_unlock(&bond->lock); 2478 read_unlock(&bond->lock);
2468 rtnl_lock(); 2479 rtnl_lock();
@@ -3158,6 +3169,12 @@ void bond_activebackup_arp_mon(struct work_struct *work)
3158 read_unlock(&bond->curr_slave_lock); 3169 read_unlock(&bond->curr_slave_lock);
3159 } 3170 }
3160 3171
3172 if (bond->send_unsol_na) {
3173 read_lock(&bond->curr_slave_lock);
3174 bond_send_unsolicited_na(bond);
3175 read_unlock(&bond->curr_slave_lock);
3176 }
3177
3161 if (bond_ab_arp_inspect(bond, delta_in_ticks)) { 3178 if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
3162 read_unlock(&bond->lock); 3179 read_unlock(&bond->lock);
3163 rtnl_lock(); 3180 rtnl_lock();
@@ -3827,6 +3844,7 @@ static int bond_close(struct net_device *bond_dev)
3827 write_lock_bh(&bond->lock); 3844 write_lock_bh(&bond->lock);
3828 3845
3829 bond->send_grat_arp = 0; 3846 bond->send_grat_arp = 0;
3847 bond->send_unsol_na = 0;
3830 3848
3831 /* signal timers not to re-arm */ 3849 /* signal timers not to re-arm */
3832 bond->kill_timers = 1; 3850 bond->kill_timers = 1;
@@ -4542,6 +4560,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
4542 bond->primary_slave = NULL; 4560 bond->primary_slave = NULL;
4543 bond->dev = bond_dev; 4561 bond->dev = bond_dev;
4544 bond->send_grat_arp = 0; 4562 bond->send_grat_arp = 0;
4563 bond->send_unsol_na = 0;
4545 bond->setup_by_slave = 0; 4564 bond->setup_by_slave = 0;
4546 INIT_LIST_HEAD(&bond->vlan_list); 4565 INIT_LIST_HEAD(&bond->vlan_list);
4547 4566
@@ -4791,6 +4810,13 @@ static int bond_check_params(struct bond_params *params)
4791 num_grat_arp = 1; 4810 num_grat_arp = 1;
4792 } 4811 }
4793 4812
4813 if (num_unsol_na < 0 || num_unsol_na > 255) {
4814 printk(KERN_WARNING DRV_NAME
4815 ": Warning: num_unsol_na (%d) not in range 0-255 so it "
4816 "was reset to 1 \n", num_unsol_na);
4817 num_unsol_na = 1;
4818 }
4819
4794 /* reset values for 802.3ad */ 4820 /* reset values for 802.3ad */
4795 if (bond_mode == BOND_MODE_8023AD) { 4821 if (bond_mode == BOND_MODE_8023AD) {
4796 if (!miimon) { 4822 if (!miimon) {
@@ -4992,6 +5018,7 @@ static int bond_check_params(struct bond_params *params)
4992 params->xmit_policy = xmit_hashtype; 5018 params->xmit_policy = xmit_hashtype;
4993 params->miimon = miimon; 5019 params->miimon = miimon;
4994 params->num_grat_arp = num_grat_arp; 5020 params->num_grat_arp = num_grat_arp;
5021 params->num_unsol_na = num_unsol_na;
4995 params->arp_interval = arp_interval; 5022 params->arp_interval = arp_interval;
4996 params->arp_validate = arp_validate_value; 5023 params->arp_validate = arp_validate_value;
4997 params->updelay = updelay; 5024 params->updelay = updelay;
@@ -5144,6 +5171,7 @@ static int __init bonding_init(void)
5144 5171
5145 register_netdevice_notifier(&bond_netdev_notifier); 5172 register_netdevice_notifier(&bond_netdev_notifier);
5146 register_inetaddr_notifier(&bond_inetaddr_notifier); 5173 register_inetaddr_notifier(&bond_inetaddr_notifier);
5174 bond_register_ipv6_notifier();
5147 5175
5148 goto out; 5176 goto out;
5149err: 5177err:
@@ -5166,6 +5194,7 @@ static void __exit bonding_exit(void)
5166{ 5194{
5167 unregister_netdevice_notifier(&bond_netdev_notifier); 5195 unregister_netdevice_notifier(&bond_netdev_notifier);
5168 unregister_inetaddr_notifier(&bond_inetaddr_notifier); 5196 unregister_inetaddr_notifier(&bond_inetaddr_notifier);
5197 bond_unregister_ipv6_notifier();
5169 5198
5170 bond_destroy_sysfs(); 5199 bond_destroy_sysfs();
5171 5200
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index e400d7dfdfc8..8788e3e33852 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -983,6 +983,47 @@ out:
983 return ret; 983 return ret;
984} 984}
985static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp); 985static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp);
986
987/*
988 * Show and set the number of unsolicted NA's to send after a failover event.
989 */
990static ssize_t bonding_show_n_unsol_na(struct device *d,
991 struct device_attribute *attr,
992 char *buf)
993{
994 struct bonding *bond = to_bond(d);
995
996 return sprintf(buf, "%d\n", bond->params.num_unsol_na);
997}
998
999static ssize_t bonding_store_n_unsol_na(struct device *d,
1000 struct device_attribute *attr,
1001 const char *buf, size_t count)
1002{
1003 int new_value, ret = count;
1004 struct bonding *bond = to_bond(d);
1005
1006 if (sscanf(buf, "%d", &new_value) != 1) {
1007 printk(KERN_ERR DRV_NAME
1008 ": %s: no num_unsol_na value specified.\n",
1009 bond->dev->name);
1010 ret = -EINVAL;
1011 goto out;
1012 }
1013 if (new_value < 0 || new_value > 255) {
1014 printk(KERN_ERR DRV_NAME
1015 ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
1016 bond->dev->name, new_value);
1017 ret = -EINVAL;
1018 goto out;
1019 } else {
1020 bond->params.num_unsol_na = new_value;
1021 }
1022out:
1023 return ret;
1024}
1025static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, bonding_show_n_unsol_na, bonding_store_n_unsol_na);
1026
986/* 1027/*
987 * Show and set the MII monitor interval. There are two tricky bits 1028 * Show and set the MII monitor interval. There are two tricky bits
988 * here. First, if MII monitoring is activated, then we must disable 1029 * here. First, if MII monitoring is activated, then we must disable
@@ -1420,6 +1461,7 @@ static struct attribute *per_bond_attrs[] = {
1420 &dev_attr_lacp_rate.attr, 1461 &dev_attr_lacp_rate.attr,
1421 &dev_attr_xmit_hash_policy.attr, 1462 &dev_attr_xmit_hash_policy.attr,
1422 &dev_attr_num_grat_arp.attr, 1463 &dev_attr_num_grat_arp.attr,
1464 &dev_attr_num_unsol_na.attr,
1423 &dev_attr_miimon.attr, 1465 &dev_attr_miimon.attr,
1424 &dev_attr_primary.attr, 1466 &dev_attr_primary.attr,
1425 &dev_attr_use_carrier.attr, 1467 &dev_attr_use_carrier.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ffb668dd6d3b..0491c7c2645b 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -19,16 +19,19 @@
19#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
20#include <linux/if_bonding.h> 20#include <linux/if_bonding.h>
21#include <linux/kobject.h> 21#include <linux/kobject.h>
22#include <linux/in6.h>
22#include "bond_3ad.h" 23#include "bond_3ad.h"
23#include "bond_alb.h" 24#include "bond_alb.h"
24 25
25#define DRV_VERSION "3.3.0" 26#define DRV_VERSION "3.4.0"
26#define DRV_RELDATE "June 10, 2008" 27#define DRV_RELDATE "October 7, 2008"
27#define DRV_NAME "bonding" 28#define DRV_NAME "bonding"
28#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" 29#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
29 30
30#define BOND_MAX_ARP_TARGETS 16 31#define BOND_MAX_ARP_TARGETS 16
31 32
33extern struct list_head bond_dev_list;
34
32#ifdef BONDING_DEBUG 35#ifdef BONDING_DEBUG
33#define dprintk(fmt, args...) \ 36#define dprintk(fmt, args...) \
34 printk(KERN_DEBUG \ 37 printk(KERN_DEBUG \
@@ -126,6 +129,7 @@ struct bond_params {
126 int xmit_policy; 129 int xmit_policy;
127 int miimon; 130 int miimon;
128 int num_grat_arp; 131 int num_grat_arp;
132 int num_unsol_na;
129 int arp_interval; 133 int arp_interval;
130 int arp_validate; 134 int arp_validate;
131 int use_carrier; 135 int use_carrier;
@@ -148,6 +152,9 @@ struct vlan_entry {
148 struct list_head vlan_list; 152 struct list_head vlan_list;
149 __be32 vlan_ip; 153 __be32 vlan_ip;
150 unsigned short vlan_id; 154 unsigned short vlan_id;
155#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
156 struct in6_addr vlan_ipv6;
157#endif
151}; 158};
152 159
153struct slave { 160struct slave {
@@ -195,6 +202,7 @@ struct bonding {
195 rwlock_t curr_slave_lock; 202 rwlock_t curr_slave_lock;
196 s8 kill_timers; 203 s8 kill_timers;
197 s8 send_grat_arp; 204 s8 send_grat_arp;
205 s8 send_unsol_na;
198 s8 setup_by_slave; 206 s8 setup_by_slave;
199 struct net_device_stats stats; 207 struct net_device_stats stats;
200#ifdef CONFIG_PROC_FS 208#ifdef CONFIG_PROC_FS
@@ -218,6 +226,9 @@ struct bonding {
218 struct delayed_work arp_work; 226 struct delayed_work arp_work;
219 struct delayed_work alb_work; 227 struct delayed_work alb_work;
220 struct delayed_work ad_work; 228 struct delayed_work ad_work;
229#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
230 struct in6_addr master_ipv6;
231#endif
221}; 232};
222 233
223/** 234/**
@@ -341,5 +352,24 @@ extern struct bond_parm_tbl xmit_hashtype_tbl[];
341extern struct bond_parm_tbl arp_validate_tbl[]; 352extern struct bond_parm_tbl arp_validate_tbl[];
342extern struct bond_parm_tbl fail_over_mac_tbl[]; 353extern struct bond_parm_tbl fail_over_mac_tbl[];
343 354
355#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
356void bond_send_unsolicited_na(struct bonding *bond);
357void bond_register_ipv6_notifier(void);
358void bond_unregister_ipv6_notifier(void);
359#else
360static inline void bond_send_unsolicited_na(struct bonding *bond)
361{
362 return;
363}
364static inline void bond_register_ipv6_notifier(void)
365{
366 return;
367}
368static inline void bond_unregister_ipv6_notifier(void)
369{
370 return;
371}
372#endif
373
344#endif /* _LINUX_BONDING_H */ 374#endif /* _LINUX_BONDING_H */
345 375