From: Herbert Xu <herbert.xu@redhat.com> Date: Thu, 24 Apr 2008 11:15:16 +0800 Subject: [xen] netfront: send fake arp when link gets carrier Message-id: 20080424031516.GA6438@gondor.apana.org.au O-Subject: [RHEL5.3 PATCH] [XEN] netfront: Send fake arp when link gets carrier Bugzilla: 441716 Hi: RHEL5.3 BZ 441716 [XEN] netfront: Send fake arp when link gets carrier As it is the Xen netfront driver will transmit a fake ARP when the link gets an IP address and when the link is brought up administratively. However, this overlooks the case when the first two events occur without a link carrier. Thus to be sure that the packet makes it out we also need to attempt a transmit when the carrier comes up which can be detected through the NETDEV_CHANGE event. This is what this patch does. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Thanks, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- Acked-by: Don Dutile <ddutile@redhat.com> diff --git a/drivers/xen/netfront/netfront.c b/drivers/xen/netfront/netfront.c index 8925e77..ce9c1cf 100644 --- a/drivers/xen/netfront/netfront.c +++ b/drivers/xen/netfront/netfront.c @@ -1999,6 +1999,22 @@ inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr) return NOTIFY_DONE; } +/* + * We also send a fake ARP if the link gets carrier. + */ +static int +netdev_notify(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; + + /* Carrier up event and is it one of our devices? */ + if (event == NETDEV_CHANGE && netif_carrier_ok(dev) && + dev->open == network_open) + (void)send_fake_arp(dev); + + return NOTIFY_DONE; +} + static void netif_disconnect_backend(struct netfront_info *info) { @@ -2062,6 +2078,10 @@ static struct notifier_block notifier_inetdev = { .priority = 0 }; +static struct notifier_block notifier_netdev = { + .notifier_call = netdev_notify, +}; + static int __init netif_init(void) { if (!is_running_on_xen()) @@ -2083,6 +2103,7 @@ static int __init netif_init(void) IPRINTK("Initialising virtual ethernet driver.\n"); (void)register_inetaddr_notifier(¬ifier_inetdev); + (void)register_netdevice_notifier(¬ifier_netdev); return xenbus_register_frontend(&netfront); } @@ -2096,6 +2117,7 @@ static void __exit netif_exit(void) if (is_initial_xendomain()) return; + unregister_netdevice_notifier(¬ifier_netdev); unregister_inetaddr_notifier(¬ifier_inetdev); return xenbus_unregister_driver(&netfront);