diff options
| author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2012-11-06 11:46:20 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-11-13 14:27:45 -0500 |
| commit | 5cb04436eef62aa8f5c482f8ec8deba391dea465 (patch) | |
| tree | 068d69d9f28c14ae515c1a6a02bcfdc04093d248 | |
| parent | 24a372cd0b87c15f8d98275d045326249155af55 (diff) | |
ipv6: add knob to send unsolicited ND on link-layer address change
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>
| -rw-r--r-- | include/linux/ipv6.h | 1 | ||||
| -rw-r--r-- | include/uapi/linux/ipv6.h | 1 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 8 | ||||
| -rw-r--r-- | net/ipv6/ndisc.c | 7 |
4 files changed, 17 insertions, 0 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index bcba48a97868..5e11905a4f01 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h | |||
| @@ -47,6 +47,7 @@ struct ipv6_devconf { | |||
| 47 | __s32 disable_ipv6; | 47 | __s32 disable_ipv6; |
| 48 | __s32 accept_dad; | 48 | __s32 accept_dad; |
| 49 | __s32 force_tllao; | 49 | __s32 force_tllao; |
| 50 | __s32 ndisc_notify; | ||
| 50 | void *sysctl; | 51 | void *sysctl; |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h index a6d7d1c536c3..5a2991cf0251 100644 --- a/include/uapi/linux/ipv6.h +++ b/include/uapi/linux/ipv6.h | |||
| @@ -157,6 +157,7 @@ enum { | |||
| 157 | DEVCONF_DISABLE_IPV6, | 157 | DEVCONF_DISABLE_IPV6, |
| 158 | DEVCONF_ACCEPT_DAD, | 158 | DEVCONF_ACCEPT_DAD, |
| 159 | DEVCONF_FORCE_TLLAO, | 159 | DEVCONF_FORCE_TLLAO, |
| 160 | DEVCONF_NDISC_NOTIFY, | ||
| 160 | DEVCONF_MAX | 161 | DEVCONF_MAX |
| 161 | }; | 162 | }; |
| 162 | 163 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fab23db8ee73..cb803b7bb0d8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -4037,6 +4037,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
| 4037 | array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; | 4037 | array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; |
| 4038 | array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; | 4038 | array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; |
| 4039 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; | 4039 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; |
| 4040 | array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; | ||
| 4040 | } | 4041 | } |
| 4041 | 4042 | ||
| 4042 | static inline size_t inet6_ifla6_size(void) | 4043 | static inline size_t inet6_ifla6_size(void) |
| @@ -4705,6 +4706,13 @@ static struct addrconf_sysctl_table | |||
| 4705 | .proc_handler = proc_dointvec | 4706 | .proc_handler = proc_dointvec |
| 4706 | }, | 4707 | }, |
| 4707 | { | 4708 | { |
| 4709 | .procname = "ndisc_notify", | ||
| 4710 | .data = &ipv6_devconf.ndisc_notify, | ||
| 4711 | .maxlen = sizeof(int), | ||
| 4712 | .mode = 0644, | ||
| 4713 | .proc_handler = proc_dointvec | ||
| 4714 | }, | ||
| 4715 | { | ||
| 4708 | /* sentinel */ | 4716 | /* sentinel */ |
| 4709 | } | 4717 | } |
| 4710 | }, | 4718 | }, |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 6ba4b54a550a..f41853bca428 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1572,11 +1572,18 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, | |||
| 1572 | { | 1572 | { |
| 1573 | struct net_device *dev = ptr; | 1573 | struct net_device *dev = ptr; |
| 1574 | struct net *net = dev_net(dev); | 1574 | struct net *net = dev_net(dev); |
| 1575 | struct inet6_dev *idev; | ||
| 1575 | 1576 | ||
| 1576 | switch (event) { | 1577 | switch (event) { |
| 1577 | case NETDEV_CHANGEADDR: | 1578 | case NETDEV_CHANGEADDR: |
| 1578 | neigh_changeaddr(&nd_tbl, dev); | 1579 | neigh_changeaddr(&nd_tbl, dev); |
| 1579 | fib6_run_gc(~0UL, net); | 1580 | fib6_run_gc(~0UL, net); |
| 1581 | idev = in6_dev_get(dev); | ||
| 1582 | if (!idev) | ||
| 1583 | break; | ||
| 1584 | if (idev->cnf.ndisc_notify) | ||
| 1585 | ndisc_send_unsol_na(dev); | ||
| 1586 | in6_dev_put(idev); | ||
| 1580 | break; | 1587 | break; |
| 1581 | case NETDEV_DOWN: | 1588 | case NETDEV_DOWN: |
| 1582 | neigh_ifdown(&nd_tbl, dev); | 1589 | neigh_ifdown(&nd_tbl, dev); |
