ipv6: add knob to send unsolicited ND on link-layer address change
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Tue, 6 Nov 2012 16:46:20 +0000 (16:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 13 Nov 2012 19:27:45 +0000 (14:27 -0500)
This patch introduces a new knob ndisc_notify. If enabled, the kernel
will transmit an unsolicited neighbour advertisement on link-layer address
change to update the neighbour tables of the corresponding hosts more quickly.

This is the equivalent to arp_notify in ipv4 world.

Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/ipv6.h
include/uapi/linux/ipv6.h
net/ipv6/addrconf.c
net/ipv6/ndisc.c

index bcba48a97868e9b38d6a92f38e5175b2474df330..5e11905a4f0194dc9c0f19aa5b02be26748378b8 100644 (file)
@@ -47,6 +47,7 @@ struct ipv6_devconf {
        __s32           disable_ipv6;
        __s32           accept_dad;
        __s32           force_tllao;
+       __s32           ndisc_notify;
        void            *sysctl;
 };
 
index a6d7d1c536c33708b84b88661184d4256299450d..5a2991cf0251d558c15d108d9ea88155240425e7 100644 (file)
@@ -157,6 +157,7 @@ enum {
        DEVCONF_DISABLE_IPV6,
        DEVCONF_ACCEPT_DAD,
        DEVCONF_FORCE_TLLAO,
+       DEVCONF_NDISC_NOTIFY,
        DEVCONF_MAX
 };
 
index fab23db8ee73fa49979172ce24623b70b7f17664..cb803b7bb0d8dc534781ee6c241bd18d88d6e90c 100644 (file)
@@ -4037,6 +4037,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
        array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
        array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
+       array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -4704,6 +4705,13 @@ static struct addrconf_sysctl_table
                        .mode           = 0644,
                        .proc_handler   = proc_dointvec
                },
+               {
+                       .procname       = "ndisc_notify",
+                       .data           = &ipv6_devconf.ndisc_notify,
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = proc_dointvec
+               },
                {
                        /* sentinel */
                }
index 6ba4b54a550a03a1a11ff3e5696b0b832abba7ea..f41853bca4289faebe21133084bd829953891611 100644 (file)
@@ -1572,11 +1572,18 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = ptr;
        struct net *net = dev_net(dev);
+       struct inet6_dev *idev;
 
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&nd_tbl, dev);
                fib6_run_gc(~0UL, net);
+               idev = in6_dev_get(dev);
+               if (!idev)
+                       break;
+               if (idev->cnf.ndisc_notify)
+                       ndisc_send_unsol_na(dev);
+               in6_dev_put(idev);
                break;
        case NETDEV_DOWN:
                neigh_ifdown(&nd_tbl, dev);