From 6d27fe89373b000d750ae0a8b9fb831357e286ed Mon Sep 17 00:00:00 2001 From: Jason Luan Date: Fri, 28 Dec 2012 15:43:06 +0800 Subject: [PATCH] xen-netback notify frontend to send gratuitous ARP. In the real network environment, some cause will lead to Active-Backup mode bonding chose new actived port. After that, the trffic, destinated to DomU by inactived port (former actived port), will be unreachable at now. DomU should send gratutious ARP initialtivly to find the new corrected path. By netback's Connected->Connected transition, frontend will watch the change, and send gratuitous ARP. Signed-off-by: Jason Luan --- diff -Nur linux-2.6.18.i686.orig/drivers/xen/netback/common.h linux-2.6.18.i686/drivers/xen/netback/common.h --- linux-2.6.18.i686.orig/drivers/xen/netback/common.h 2013-01-17 14:21:50.000000000 +0800 +++ linux-2.6.18.i686/drivers/xen/netback/common.h 2013-01-17 14:32:48.000000000 +0800 @@ -151,6 +151,8 @@ void *netback_accel_priv; /* The accelerator that this backend is currently using */ struct netback_accelerator *accelerator; + + struct notifier_block vif_notifier; }; #define NETBACK_ACCEL_VERSION 0x00010001 diff -Nur linux-2.6.18.i686.orig/drivers/xen/netback/xenbus.c linux-2.6.18.i686/drivers/xen/netback/xenbus.c --- linux-2.6.18.i686.orig/drivers/xen/netback/xenbus.c 2013-01-17 14:21:50.000000000 +0800 +++ linux-2.6.18.i686/drivers/xen/netback/xenbus.c 2013-01-17 14:34:02.000000000 +0800 @@ -33,10 +33,73 @@ static void connect(struct backend_info *); static void backend_create_netif(struct backend_info *be); +/** + * By Connected->Connected transition, netfront will watch the change and + * send gratuitous ARP. + */ +static void notify_front_arping(struct xenbus_device *dev) +{ + struct xenbus_transaction xbt; + int err; + + if (xenbus_read_driver_state(dev->nodename) != XenbusStateConnected) + return; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + printk(KERN_ALERT "Error starting transaction"); + return; + } + + err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); + if(err) { + printk(KERN_ALERT "Error writing the state"); + xenbus_transaction_end(xbt, 1); + return; + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + printk(KERN_ALERT "Error ending transaction"); + + return; +} + +#define nb_to_backend(nb) container_of(nb, struct backend_info, vif_notifier) +/** + * When network condition of vif change, notify the frontend. + */ +static int netback_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct net_device *event_dev = ptr; + struct backend_info *be = nb_to_backend(this); + + pr_debug("event_dev: %s, event: %lx\n", + event_dev ? event_dev->name : "None", event); + + if (!be->netif) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_BONDING_FAILOVER: + /* Notify frontend to Send gratuitous ARP */ + notify_front_arping(be->dev); + break; + } + + return NOTIFY_DONE; +} + static int netback_remove(struct xenbus_device *dev) { struct backend_info *be = dev->dev.driver_data; + unregister_netdevice_notifier(&be->vif_notifier); + netback_remove_accelerators(be, dev); if (be->netif) { @@ -132,6 +195,10 @@ /* This kicks hotplug scripts, so do it immediately. */ backend_create_netif(be); + /* Register Frontend Event Notify */ + be->vif_notifier.notifier_call = netback_netdev_event; + register_netdevice_notifier(&be->vif_notifier); + return 0; abort_transaction: