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 | __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 | ||
| @@ -157,6 +157,7 @@ enum { · 156 unmodified lines | |||
| 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 | ||
| @@ -4037,6 +4037,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, · 4036 unmodified lines | |||
| 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) |
| @@ -4704,6 +4705,13 @@ static struct addrconf_sysctl_table · 661 unmodified lines | |||
| 4704 | .mode = 0644, | 4705 | .mode = 0644, |
| 4705 | .proc_handler = proc_dointvec | 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 | /* sentinel */ | 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 | 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); |