aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2005-06-26 17:52:20 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-26 17:52:20 -0400
commitc3ade5cad07f4d67f2e16a28f3c73d9483a55e0e (patch)
tree198f479dbcb793ad84cbb23d8f5f049253de5f07
parent12755c16a9e4fa2fd5b0ca1963e83d671a6251da (diff)
bonding: gratuitous ARP
Add support for generating gratuitous ARPs in bonding active-backup mode when failovers occur. Includes support for VLAN tagging the ARPs as needed. Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
-rw-r--r--drivers/net/bonding/bond_main.c283
-rw-r--r--drivers/net/bonding/bonding.h6
2 files changed, 255 insertions, 34 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 269a5e407349..545f6fe025a8 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -475,7 +475,10 @@
475 * Solution is to move call to dev_remove_pack outside of the 475 * Solution is to move call to dev_remove_pack outside of the
476 * spinlock. 476 * spinlock.
477 * Set version to 2.6.1. 477 * Set version to 2.6.1.
478 * 478 * 2005/06/05 - Jay Vosburgh <fubar@us.ibm.com>
479 * - Support for generating gratuitous ARPs in active-backup mode.
480 * Includes support for VLAN tagging all bonding-generated ARPs
481 * as needed. Set version to 2.6.2.
479 */ 482 */
480 483
481//#define BONDING_DEBUG 1 484//#define BONDING_DEBUG 1
@@ -519,6 +522,7 @@
519#include <linux/ethtool.h> 522#include <linux/ethtool.h>
520#include <linux/if_vlan.h> 523#include <linux/if_vlan.h>
521#include <linux/if_bonding.h> 524#include <linux/if_bonding.h>
525#include <net/route.h>
522#include "bonding.h" 526#include "bonding.h"
523#include "bond_3ad.h" 527#include "bond_3ad.h"
524#include "bond_alb.h" 528#include "bond_alb.h"
@@ -574,7 +578,6 @@ static struct proc_dir_entry *bond_proc_dir = NULL;
574 578
575static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; 579static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
576static int arp_ip_count = 0; 580static int arp_ip_count = 0;
577static u32 my_ip = 0;
578static int bond_mode = BOND_MODE_ROUNDROBIN; 581static int bond_mode = BOND_MODE_ROUNDROBIN;
579static int lacp_fast = 0; 582static int lacp_fast = 0;
580static int app_abi_ver = 0; 583static int app_abi_ver = 0;
@@ -611,6 +614,7 @@ static struct bond_parm_tbl bond_mode_tbl[] = {
611/*-------------------------- Forward declarations ---------------------------*/ 614/*-------------------------- Forward declarations ---------------------------*/
612 615
613static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode); 616static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);
617static void bond_send_gratuitous_arp(struct bonding *bond);
614 618
615/*---------------------------- General routines -----------------------------*/ 619/*---------------------------- General routines -----------------------------*/
616 620
@@ -659,6 +663,7 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
659 663
660 INIT_LIST_HEAD(&vlan->vlan_list); 664 INIT_LIST_HEAD(&vlan->vlan_list);
661 vlan->vlan_id = vlan_id; 665 vlan->vlan_id = vlan_id;
666 vlan->vlan_ip = 0;
662 667
663 write_lock_bh(&bond->lock); 668 write_lock_bh(&bond->lock);
664 669
@@ -1468,16 +1473,6 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act
1468 } 1473 }
1469 } 1474 }
1470 1475
1471 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
1472 if (old_active) {
1473 bond_set_slave_inactive_flags(old_active);
1474 }
1475
1476 if (new_active) {
1477 bond_set_slave_active_flags(new_active);
1478 }
1479 }
1480
1481 if (USES_PRIMARY(bond->params.mode)) { 1476 if (USES_PRIMARY(bond->params.mode)) {
1482 bond_mc_swap(bond, new_active, old_active); 1477 bond_mc_swap(bond, new_active, old_active);
1483 } 1478 }
@@ -1488,6 +1483,17 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act
1488 } else { 1483 } else {
1489 bond->curr_active_slave = new_active; 1484 bond->curr_active_slave = new_active;
1490 } 1485 }
1486
1487 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
1488 if (old_active) {
1489 bond_set_slave_inactive_flags(old_active);
1490 }
1491
1492 if (new_active) {
1493 bond_set_slave_active_flags(new_active);
1494 }
1495 bond_send_gratuitous_arp(bond);
1496 }
1491} 1497}
1492 1498
1493/** 1499/**
@@ -2694,15 +2700,180 @@ out:
2694 read_unlock(&bond->lock); 2700 read_unlock(&bond->lock);
2695} 2701}
2696 2702
2703
2704static u32 bond_glean_dev_ip(struct net_device *dev)
2705{
2706 struct in_device *idev;
2707 struct in_ifaddr *ifa;
2708 u32 addr = 0;
2709
2710 if (!dev)
2711 return 0;
2712
2713 rcu_read_lock();
2714 idev = __in_dev_get(dev);
2715 if (!idev)
2716 goto out;
2717
2718 ifa = idev->ifa_list;
2719 if (!ifa)
2720 goto out;
2721
2722 addr = ifa->ifa_local;
2723out:
2724 rcu_read_unlock();
2725 return addr;
2726}
2727
2728static int bond_has_ip(struct bonding *bond)
2729{
2730 struct vlan_entry *vlan, *vlan_next;
2731
2732 if (bond->master_ip)
2733 return 1;
2734
2735 if (list_empty(&bond->vlan_list))
2736 return 0;
2737
2738 list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
2739 vlan_list) {
2740 if (vlan->vlan_ip)
2741 return 1;
2742 }
2743
2744 return 0;
2745}
2746
2747/*
2748 * We go to the (large) trouble of VLAN tagging ARP frames because
2749 * switches in VLAN mode (especially if ports are configured as
2750 * "native" to a VLAN) might not pass non-tagged frames.
2751 */
2752static void bond_arp_send(struct net_device *slave_dev, int arp_op, u32 dest_ip, u32 src_ip, unsigned short vlan_id)
2753{
2754 struct sk_buff *skb;
2755
2756 dprintk("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
2757 slave_dev->name, dest_ip, src_ip, vlan_id);
2758
2759 skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
2760 NULL, slave_dev->dev_addr, NULL);
2761
2762 if (!skb) {
2763 printk(KERN_ERR DRV_NAME ": ARP packet allocation failed\n");
2764 return;
2765 }
2766 if (vlan_id) {
2767 skb = vlan_put_tag(skb, vlan_id);
2768 if (!skb) {
2769 printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
2770 return;
2771 }
2772 }
2773 arp_xmit(skb);
2774}
2775
2776
2697static void bond_arp_send_all(struct bonding *bond, struct slave *slave) 2777static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
2698{ 2778{
2699 int i; 2779 int i, vlan_id, rv;
2700 u32 *targets = bond->params.arp_targets; 2780 u32 *targets = bond->params.arp_targets;
2781 struct vlan_entry *vlan, *vlan_next;
2782 struct net_device *vlan_dev;
2783 struct flowi fl;
2784 struct rtable *rt;
2701 2785
2702 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { 2786 for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
2703 arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev, 2787 dprintk("basa: target %x\n", targets[i]);
2704 my_ip, NULL, slave->dev->dev_addr, 2788 if (list_empty(&bond->vlan_list)) {
2705 NULL); 2789 dprintk("basa: empty vlan: arp_send\n");
2790 bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
2791 bond->master_ip, 0);
2792 continue;
2793 }
2794
2795 /*
2796 * If VLANs are configured, we do a route lookup to
2797 * determine which VLAN interface would be used, so we
2798 * can tag the ARP with the proper VLAN tag.
2799 */
2800 memset(&fl, 0, sizeof(fl));
2801 fl.fl4_dst = targets[i];
2802 fl.fl4_tos = RTO_ONLINK;
2803
2804 rv = ip_route_output_key(&rt, &fl);
2805 if (rv) {
2806 if (net_ratelimit()) {
2807 printk(KERN_WARNING DRV_NAME
2808 ": %s: no route to arp_ip_target %u.%u.%u.%u\n",
2809 bond->dev->name, NIPQUAD(fl.fl4_dst));
2810 }
2811 continue;
2812 }
2813
2814 /*
2815 * This target is not on a VLAN
2816 */
2817 if (rt->u.dst.dev == bond->dev) {
2818 dprintk("basa: rtdev == bond->dev: arp_send\n");
2819 bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
2820 bond->master_ip, 0);
2821 continue;
2822 }
2823
2824 vlan_id = 0;
2825 list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
2826 vlan_list) {
2827 vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
2828 if (vlan_dev == rt->u.dst.dev) {
2829 vlan_id = vlan->vlan_id;
2830 dprintk("basa: vlan match on %s %d\n",
2831 vlan_dev->name, vlan_id);
2832 break;
2833 }
2834 }
2835
2836 if (vlan_id) {
2837 bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
2838 vlan->vlan_ip, vlan_id);
2839 continue;
2840 }
2841
2842 if (net_ratelimit()) {
2843 printk(KERN_WARNING DRV_NAME
2844 ": %s: no path to arp_ip_target %u.%u.%u.%u via rt.dev %s\n",
2845 bond->dev->name, NIPQUAD(fl.fl4_dst),
2846 rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
2847 }
2848 }
2849}
2850
2851/*
2852 * Kick out a gratuitous ARP for an IP on the bonding master plus one
2853 * for each VLAN above us.
2854 */
2855static void bond_send_gratuitous_arp(struct bonding *bond)
2856{
2857 struct slave *slave = bond->curr_active_slave;
2858 struct vlan_entry *vlan;
2859 struct net_device *vlan_dev;
2860
2861 dprintk("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name,
2862 slave ? slave->dev->name : "NULL");
2863 if (!slave)
2864 return;
2865
2866 if (bond->master_ip) {
2867 bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip,
2868 bond->master_ip, 0);
2869 }
2870
2871 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
2872 vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
2873 if (vlan->vlan_ip) {
2874 bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip,
2875 vlan->vlan_ip, vlan->vlan_id);
2876 }
2706 } 2877 }
2707} 2878}
2708 2879
@@ -2781,7 +2952,7 @@ static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
2781 */ 2952 */
2782 if (((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || 2953 if (((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
2783 (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && 2954 (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
2784 my_ip)) { 2955 bond_has_ip(bond))) {
2785 2956
2786 slave->link = BOND_LINK_DOWN; 2957 slave->link = BOND_LINK_DOWN;
2787 slave->state = BOND_STATE_BACKUP; 2958 slave->state = BOND_STATE_BACKUP;
@@ -2920,7 +3091,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev)
2920 if ((slave != bond->curr_active_slave) && 3091 if ((slave != bond->curr_active_slave) &&
2921 (!bond->current_arp_slave) && 3092 (!bond->current_arp_slave) &&
2922 (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) && 3093 (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
2923 my_ip)) { 3094 bond_has_ip(bond))) {
2924 /* a backup slave has gone down; three times 3095 /* a backup slave has gone down; three times
2925 * the delta allows the current slave to be 3096 * the delta allows the current slave to be
2926 * taken out before the backup slave. 3097 * taken out before the backup slave.
@@ -2966,8 +3137,8 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev)
2966 * if it is up and needs to take over as the curr_active_slave 3137 * if it is up and needs to take over as the curr_active_slave
2967 */ 3138 */
2968 if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || 3139 if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
2969 (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && 3140 (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
2970 my_ip)) && 3141 bond_has_ip(bond))) &&
2971 ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) { 3142 ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
2972 3143
2973 slave->link = BOND_LINK_DOWN; 3144 slave->link = BOND_LINK_DOWN;
@@ -3019,7 +3190,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev)
3019 /* the current slave must tx an arp to ensure backup slaves 3190 /* the current slave must tx an arp to ensure backup slaves
3020 * rx traffic 3191 * rx traffic
3021 */ 3192 */
3022 if (slave && my_ip) { 3193 if (slave && bond_has_ip(bond)) {
3023 bond_arp_send_all(bond, slave); 3194 bond_arp_send_all(bond, slave);
3024 } 3195 }
3025 } 3196 }
@@ -3471,10 +3642,67 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
3471 return NOTIFY_DONE; 3642 return NOTIFY_DONE;
3472} 3643}
3473 3644
3645/*
3646 * bond_inetaddr_event: handle inetaddr notifier chain events.
3647 *
3648 * We keep track of device IPs primarily to use as source addresses in
3649 * ARP monitor probes (rather than spewing out broadcasts all the time).
3650 *
3651 * We track one IP for the main device (if it has one), plus one per VLAN.
3652 */
3653static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
3654{
3655 struct in_ifaddr *ifa = ptr;
3656 struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev;
3657 struct bonding *bond, *bond_next;
3658 struct vlan_entry *vlan, *vlan_next;
3659
3660 list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) {
3661 if (bond->dev == event_dev) {
3662 switch (event) {
3663 case NETDEV_UP:
3664 bond->master_ip = ifa->ifa_local;
3665 return NOTIFY_OK;
3666 case NETDEV_DOWN:
3667 bond->master_ip = bond_glean_dev_ip(bond->dev);
3668 return NOTIFY_OK;
3669 default:
3670 return NOTIFY_DONE;
3671 }
3672 }
3673
3674 if (list_empty(&bond->vlan_list))
3675 continue;
3676
3677 list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
3678 vlan_list) {
3679 vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
3680 if (vlan_dev == event_dev) {
3681 switch (event) {
3682 case NETDEV_UP:
3683 vlan->vlan_ip = ifa->ifa_local;
3684 return NOTIFY_OK;
3685 case NETDEV_DOWN:
3686 vlan->vlan_ip =
3687 bond_glean_dev_ip(vlan_dev);
3688 return NOTIFY_OK;
3689 default:
3690 return NOTIFY_DONE;
3691 }
3692 }
3693 }
3694 }
3695 return NOTIFY_DONE;
3696}
3697
3474static struct notifier_block bond_netdev_notifier = { 3698static struct notifier_block bond_netdev_notifier = {
3475 .notifier_call = bond_netdev_event, 3699 .notifier_call = bond_netdev_event,
3476}; 3700};
3477 3701
3702static struct notifier_block bond_inetaddr_notifier = {
3703 .notifier_call = bond_inetaddr_event,
3704};
3705
3478/*-------------------------- Packet type handling ---------------------------*/ 3706/*-------------------------- Packet type handling ---------------------------*/
3479 3707
3480/* register to receive lacpdus on a bond */ 3708/* register to receive lacpdus on a bond */
@@ -4060,17 +4288,6 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
4060 struct bonding *bond = bond_dev->priv; 4288 struct bonding *bond = bond_dev->priv;
4061 int res = 1; 4289 int res = 1;
4062 4290
4063 /* if we are sending arp packets, try to at least
4064 identify our own ip address */
4065 if (bond->params.arp_interval && !my_ip &&
4066 (skb->protocol == __constant_htons(ETH_P_ARP))) {
4067 char *the_ip = (char *)skb->data +
4068 sizeof(struct ethhdr) +
4069 sizeof(struct arphdr) +
4070 ETH_ALEN;
4071 memcpy(&my_ip, the_ip, 4);
4072 }
4073
4074 read_lock(&bond->lock); 4291 read_lock(&bond->lock);
4075 read_lock(&bond->curr_slave_lock); 4292 read_lock(&bond->curr_slave_lock);
4076 4293
@@ -4669,6 +4886,7 @@ static int __init bonding_init(void)
4669 4886
4670 rtnl_unlock(); 4887 rtnl_unlock();
4671 register_netdevice_notifier(&bond_netdev_notifier); 4888 register_netdevice_notifier(&bond_netdev_notifier);
4889 register_inetaddr_notifier(&bond_inetaddr_notifier);
4672 4890
4673 return 0; 4891 return 0;
4674 4892
@@ -4684,6 +4902,7 @@ out_err:
4684static void __exit bonding_exit(void) 4902static void __exit bonding_exit(void)
4685{ 4903{
4686 unregister_netdevice_notifier(&bond_netdev_notifier); 4904 unregister_netdevice_notifier(&bond_netdev_notifier);
4905 unregister_inetaddr_notifier(&bond_inetaddr_notifier);
4687 4906
4688 rtnl_lock(); 4907 rtnl_lock();
4689 bond_free_all(); 4908 bond_free_all();
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 8c325308489d..6558af22eda4 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -36,8 +36,8 @@
36#include "bond_3ad.h" 36#include "bond_3ad.h"
37#include "bond_alb.h" 37#include "bond_alb.h"
38 38
39#define DRV_VERSION "2.6.1" 39#define DRV_VERSION "2.6.2"
40#define DRV_RELDATE "October 29, 2004" 40#define DRV_RELDATE "June 5, 2005"
41#define DRV_NAME "bonding" 41#define DRV_NAME "bonding"
42#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" 42#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
43 43
@@ -149,6 +149,7 @@ struct bond_params {
149 149
150struct vlan_entry { 150struct vlan_entry {
151 struct list_head vlan_list; 151 struct list_head vlan_list;
152 u32 vlan_ip;
152 unsigned short vlan_id; 153 unsigned short vlan_id;
153}; 154};
154 155
@@ -197,6 +198,7 @@ struct bonding {
197#endif /* CONFIG_PROC_FS */ 198#endif /* CONFIG_PROC_FS */
198 struct list_head bond_list; 199 struct list_head bond_list;
199 struct dev_mc_list *mc_list; 200 struct dev_mc_list *mc_list;
201 u32 master_ip;
200 u16 flags; 202 u16 flags;
201 struct ad_bond_info ad_info; 203 struct ad_bond_info ad_info;
202 struct alb_bond_info alb_info; 204 struct alb_bond_info alb_info;