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.
Unified · Split
| @@ -47,6 +47,7 @@ struct ipv6_devconf { · 46 unmodified lines | ||
| 47 | 47 | __s32 disable_ipv6; |
| 48 | 48 | __s32 accept_dad; |
| 49 | 49 | __s32 force_tllao; |
| 50 | + __s32 ndisc_notify; | |
| 50 | 51 | void *sysctl; |
| 51 | 52 | }; |
| 52 | 53 | |
| @@ -157,6 +157,7 @@ enum { · 156 unmodified lines | ||
| 157 | 157 | DEVCONF_DISABLE_IPV6, |
| 158 | 158 | DEVCONF_ACCEPT_DAD, |
| 159 | 159 | DEVCONF_FORCE_TLLAO, |
| 160 | + DEVCONF_NDISC_NOTIFY, | |
| 160 | 161 | DEVCONF_MAX |
| 161 | 162 | }; |
| 162 | 163 | |
| @@ -4037,6 +4037,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, · 4036 unmodified lines | ||
| 4037 | 4037 | array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; |
| 4038 | 4038 | array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; |
| 4039 | 4039 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; |
| 4040 | + array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; | |
| 4040 | 4041 | } |
| 4041 | 4042 | |
| 4042 | 4043 | static inline size_t inet6_ifla6_size(void) |
| @@ -4704,6 +4705,13 @@ static struct addrconf_sysctl_table · 661 unmodified lines | ||
| 4704 | 4705 | .mode = 0644, |
| 4705 | 4706 | .proc_handler = proc_dointvec |
| 4706 | 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 | + }, | |
| 4707 | 4715 | { |
| 4708 | 4716 | /* sentinel */ |
| 4709 | 4717 | } |
| @@ -1572,11 +1572,18 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, · 1571 unmodified lines | ||
| 1572 | 1572 | { |
| 1573 | 1573 | struct net_device *dev = ptr; |
| 1574 | 1574 | struct net *net = dev_net(dev); |
| 1575 | + struct inet6_dev *idev; | |
| 1575 | 1576 | |
| 1576 | 1577 | switch (event) { |
| 1577 | 1578 | case NETDEV_CHANGEADDR: |
| 1578 | 1579 | neigh_changeaddr(&nd_tbl, dev); |
| 1579 | 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 | 1587 | break; |
| 1581 | 1588 | case NETDEV_DOWN: |
| 1582 | 1589 | neigh_ifdown(&nd_tbl, dev); |