Subject: Re: [Xen-devel] xen-netback notify DomU to send ARP.

From: jianhai luan <[email-masked]>
Date: Thu, 10 Jan 2013 15:00:15 +0800

The patch main to fix the below circumstance:
Bonding  run in Active-Backup mode.
Out PC --> switcher
             port A --> eth0 --> bond0 --> xenbr0 --> netbackend --> DomU
             port B -- eth1 /
Or

Out PC (R)--> switcher A --> eth0 --> bond0 --> xenbr0 --> netbackend 
--> DomU
             \ switcher B -- eth1 /

When Switcher Port A (active port) don't reach, or switcher A don't reach,
the surroundings will changed to the below circumstance.
Out PC --> switcher
             port A -X- eth0 -- bond0 -- xenbr0 -- netbackend -- DomU
             port B -- eth1 /
Or

Out PC (R)--> switcher A -X- eth0 -- bond0 -- xenbr0 -- netbackend -- DomU
             \ switcher B -- eth1 /

So, the former traffic will be unreachable before find the correct path 
(by sending
ARP request).

So, the patch is main to found the bonding change event, and gratutious 
ARP initialtivly
to out PC find the correct path.

the correct path should be the below circumstance:
Out PC --> switcher
             port A -X- eth0 --> bond0 --> xenbr0 --> netbackend --> DomU
             port B --> eth1 /
Or

Out PC (R)--> switcher A -X- eth0 --> bond0 --> xenbr0 --> netbackend 
--> DomU
             \ switcher B --> eth1 /

Thanks,
Jason
From cd5a33f9137a60f27c2a8c6c77a520d2df356c7a Mon Sep 17 00:00:00 2001
From: Jason Luan <[email-masked]>
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 <[email-masked]>
---
 drivers/net/xen-netback/xenbus.c |   68 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 410018c..ebea683 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -26,6 +26,7 @@ struct backend_info {
 	struct xenvif *vif;
 	enum xenbus_state frontend_state;
 	struct xenbus_watch hotplug_status_watch;
+	struct notifier_block vif_notifier;
 	u8 have_hotplug_status_watch:1;
 };
 
@@ -34,11 +35,74 @@ static void connect(struct backend_info *);
 static void backend_create_xenvif(struct backend_info *be);
 static void unregister_hotplug_status_watch(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) {
+		pr_fmt("Error starting transaction");
+		return;
+	}
+
+	err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state);
+	if (err) {
+		pr_fmt("Error writing the state");
+		goto abort;
+	}
+
+	err = xenbus_transaction_end(xbt, 0);
+	if (err == -EAGAIN)
+		goto again;
+	if (err)
+		pr_fmt("Error ending transaction");
+
+	return;
+abort:
+	xenbus_transaction_end(xbt, 1);
+}
+
+#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->vif)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_NOTIFY_PEERS:
+		/* 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_get_drvdata(&dev->dev);
 
 	unregister_hotplug_status_watch(be);
+	unregister_netdevice_notifier(&be->vif_notifier);
 	if (be->vif) {
 		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
 		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
@@ -129,6 +193,10 @@ static int netback_probe(struct xenbus_device *dev,
 	/* This kicks hotplug scripts, so do it immediately. */
 	backend_create_xenvif(be);
 
+	/* Register Frontend Event Notify */
+	be->vif_notifier.notifier_call = netback_netdev_event;
+	register_netdevice_notifier(&be->vif_notifier);
+
 	return 0;
 
 abort_transaction:
-- 
1.7.6.5