diff options
author | Neil Horman <nhorman@tuxdriver.com> | 2007-04-25 20:08:10 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:23:43 -0400 |
commit | 95c385b4d5a71b8ad552aecaa968ea46d7da2f6a (patch) | |
tree | 49d8e60418cb4eeb0c9ed79fd095af50f6ec6623 /net/ipv6/addrconf.c | |
parent | 502b093569e48db264831be7966e1c447de2f52f (diff) |
[IPV6] ADDRCONF: Optimistic Duplicate Address Detection (RFC 4429) Support.
Nominally an autoconfigured IPv6 address is added to an interface in the
Tentative state (as per RFC 2462). Addresses in this state remain in this
state while the Duplicate Address Detection process operates on them to
determine their uniqueness on the network. During this period, these
tentative addresses may not be used for communication, increasing the time
before a node may be able to communicate on a network. Using Optimistic
Duplicate Address Detection, autoconfigured addresses may be used
immediately for communication on the network, as long as certain rules are
followed to avoid conflicts with other nodes during the Duplicate Address
Detection process.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 106 |
1 files changed, 91 insertions, 15 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e035896657bc..38274c20eaa2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -530,6 +530,16 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
530 | 530 | ||
531 | ifa->rt = rt; | 531 | ifa->rt = rt; |
532 | 532 | ||
533 | /* | ||
534 | * part one of RFC 4429, section 3.3 | ||
535 | * We should not configure an address as | ||
536 | * optimistic if we do not yet know the link | ||
537 | * layer address of our nexhop router | ||
538 | */ | ||
539 | |||
540 | if (rt->rt6i_nexthop == NULL) | ||
541 | ifa->flags &= ~IFA_F_OPTIMISTIC; | ||
542 | |||
533 | ifa->idev = idev; | 543 | ifa->idev = idev; |
534 | in6_dev_hold(idev); | 544 | in6_dev_hold(idev); |
535 | /* For caller */ | 545 | /* For caller */ |
@@ -706,6 +716,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
706 | int tmp_plen; | 716 | int tmp_plen; |
707 | int ret = 0; | 717 | int ret = 0; |
708 | int max_addresses; | 718 | int max_addresses; |
719 | u32 addr_flags; | ||
709 | 720 | ||
710 | write_lock(&idev->lock); | 721 | write_lock(&idev->lock); |
711 | if (ift) { | 722 | if (ift) { |
@@ -763,10 +774,17 @@ retry: | |||
763 | spin_unlock_bh(&ifp->lock); | 774 | spin_unlock_bh(&ifp->lock); |
764 | 775 | ||
765 | write_unlock(&idev->lock); | 776 | write_unlock(&idev->lock); |
777 | |||
778 | addr_flags = IFA_F_TEMPORARY; | ||
779 | /* set in addrconf_prefix_rcv() */ | ||
780 | if (ifp->flags & IFA_F_OPTIMISTIC) | ||
781 | addr_flags |= IFA_F_OPTIMISTIC; | ||
782 | |||
766 | ift = !max_addresses || | 783 | ift = !max_addresses || |
767 | ipv6_count_addresses(idev) < max_addresses ? | 784 | ipv6_count_addresses(idev) < max_addresses ? |
768 | ipv6_add_addr(idev, &addr, tmp_plen, | 785 | ipv6_add_addr(idev, &addr, tmp_plen, |
769 | ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, IFA_F_TEMPORARY) : NULL; | 786 | ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, |
787 | addr_flags) : NULL; | ||
770 | if (!ift || IS_ERR(ift)) { | 788 | if (!ift || IS_ERR(ift)) { |
771 | in6_ifa_put(ifp); | 789 | in6_ifa_put(ifp); |
772 | in6_dev_put(idev); | 790 | in6_dev_put(idev); |
@@ -898,13 +916,14 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
898 | * - Tentative Address (RFC2462 section 5.4) | 916 | * - Tentative Address (RFC2462 section 5.4) |
899 | * - A tentative address is not considered | 917 | * - A tentative address is not considered |
900 | * "assigned to an interface" in the traditional | 918 | * "assigned to an interface" in the traditional |
901 | * sense. | 919 | * sense, unless it is also flagged as optimistic. |
902 | * - Candidate Source Address (section 4) | 920 | * - Candidate Source Address (section 4) |
903 | * - In any case, anycast addresses, multicast | 921 | * - In any case, anycast addresses, multicast |
904 | * addresses, and the unspecified address MUST | 922 | * addresses, and the unspecified address MUST |
905 | * NOT be included in a candidate set. | 923 | * NOT be included in a candidate set. |
906 | */ | 924 | */ |
907 | if (ifa->flags & IFA_F_TENTATIVE) | 925 | if ((ifa->flags & IFA_F_TENTATIVE) && |
926 | (!(ifa->flags & IFA_F_OPTIMISTIC))) | ||
908 | continue; | 927 | continue; |
909 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || | 928 | if (unlikely(score.addr_type == IPV6_ADDR_ANY || |
910 | score.addr_type & IPV6_ADDR_MULTICAST)) { | 929 | score.addr_type & IPV6_ADDR_MULTICAST)) { |
@@ -963,15 +982,17 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
963 | } | 982 | } |
964 | } | 983 | } |
965 | 984 | ||
966 | /* Rule 3: Avoid deprecated address */ | 985 | /* Rule 3: Avoid deprecated and optimistic addresses */ |
967 | if (hiscore.rule < 3) { | 986 | if (hiscore.rule < 3) { |
968 | if (ipv6_saddr_preferred(hiscore.addr_type) || | 987 | if (ipv6_saddr_preferred(hiscore.addr_type) || |
969 | !(ifa_result->flags & IFA_F_DEPRECATED)) | 988 | (((ifa_result->flags & |
989 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) | ||
970 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; | 990 | hiscore.attrs |= IPV6_SADDR_SCORE_PREFERRED; |
971 | hiscore.rule++; | 991 | hiscore.rule++; |
972 | } | 992 | } |
973 | if (ipv6_saddr_preferred(score.addr_type) || | 993 | if (ipv6_saddr_preferred(score.addr_type) || |
974 | !(ifa->flags & IFA_F_DEPRECATED)) { | 994 | (((ifa_result->flags & |
995 | (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) { | ||
975 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; | 996 | score.attrs |= IPV6_SADDR_SCORE_PREFERRED; |
976 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { | 997 | if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) { |
977 | score.rule = 3; | 998 | score.rule = 3; |
@@ -1111,7 +1132,8 @@ int ipv6_get_saddr(struct dst_entry *dst, | |||
1111 | 1132 | ||
1112 | EXPORT_SYMBOL(ipv6_get_saddr); | 1133 | EXPORT_SYMBOL(ipv6_get_saddr); |
1113 | 1134 | ||
1114 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) | 1135 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
1136 | unsigned char banned_flags) | ||
1115 | { | 1137 | { |
1116 | struct inet6_dev *idev; | 1138 | struct inet6_dev *idev; |
1117 | int err = -EADDRNOTAVAIL; | 1139 | int err = -EADDRNOTAVAIL; |
@@ -1122,7 +1144,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) | |||
1122 | 1144 | ||
1123 | read_lock_bh(&idev->lock); | 1145 | read_lock_bh(&idev->lock); |
1124 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1146 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { |
1125 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1147 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { |
1126 | ipv6_addr_copy(addr, &ifp->addr); | 1148 | ipv6_addr_copy(addr, &ifp->addr); |
1127 | err = 0; | 1149 | err = 0; |
1128 | break; | 1150 | break; |
@@ -1674,6 +1696,13 @@ ok: | |||
1674 | 1696 | ||
1675 | if (ifp == NULL && valid_lft) { | 1697 | if (ifp == NULL && valid_lft) { |
1676 | int max_addresses = in6_dev->cnf.max_addresses; | 1698 | int max_addresses = in6_dev->cnf.max_addresses; |
1699 | u32 addr_flags = 0; | ||
1700 | |||
1701 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
1702 | if (in6_dev->cnf.optimistic_dad && | ||
1703 | !ipv6_devconf.forwarding) | ||
1704 | addr_flags = IFA_F_OPTIMISTIC; | ||
1705 | #endif | ||
1677 | 1706 | ||
1678 | /* Do not allow to create too much of autoconfigured | 1707 | /* Do not allow to create too much of autoconfigured |
1679 | * addresses; this would be too easy way to crash kernel. | 1708 | * addresses; this would be too easy way to crash kernel. |
@@ -1681,7 +1710,8 @@ ok: | |||
1681 | if (!max_addresses || | 1710 | if (!max_addresses || |
1682 | ipv6_count_addresses(in6_dev) < max_addresses) | 1711 | ipv6_count_addresses(in6_dev) < max_addresses) |
1683 | ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len, | 1712 | ifp = ipv6_add_addr(in6_dev, &addr, pinfo->prefix_len, |
1684 | addr_type&IPV6_ADDR_SCOPE_MASK, 0); | 1713 | addr_type&IPV6_ADDR_SCOPE_MASK, |
1714 | addr_flags); | ||
1685 | 1715 | ||
1686 | if (!ifp || IS_ERR(ifp)) { | 1716 | if (!ifp || IS_ERR(ifp)) { |
1687 | in6_dev_put(in6_dev); | 1717 | in6_dev_put(in6_dev); |
@@ -1889,6 +1919,11 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, | |||
1889 | 1919 | ||
1890 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, | 1920 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, |
1891 | jiffies_to_clock_t(valid_lft * HZ), flags); | 1921 | jiffies_to_clock_t(valid_lft * HZ), flags); |
1922 | /* | ||
1923 | * Note that section 3.1 of RFC 4429 indicates | ||
1924 | * that the Optimistic flag should not be set for | ||
1925 | * manually configured addresses | ||
1926 | */ | ||
1892 | addrconf_dad_start(ifp, 0); | 1927 | addrconf_dad_start(ifp, 0); |
1893 | in6_ifa_put(ifp); | 1928 | in6_ifa_put(ifp); |
1894 | addrconf_verify(0); | 1929 | addrconf_verify(0); |
@@ -2065,8 +2100,16 @@ static void init_loopback(struct net_device *dev) | |||
2065 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) | 2100 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) |
2066 | { | 2101 | { |
2067 | struct inet6_ifaddr * ifp; | 2102 | struct inet6_ifaddr * ifp; |
2103 | u32 addr_flags = IFA_F_PERMANENT; | ||
2104 | |||
2105 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
2106 | if (idev->cnf.optimistic_dad && | ||
2107 | !ipv6_devconf.forwarding) | ||
2108 | addr_flags |= IFA_F_OPTIMISTIC; | ||
2109 | #endif | ||
2068 | 2110 | ||
2069 | ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT); | 2111 | |
2112 | ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, addr_flags); | ||
2070 | if (!IS_ERR(ifp)) { | 2113 | if (!IS_ERR(ifp)) { |
2071 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); | 2114 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); |
2072 | addrconf_dad_start(ifp, 0); | 2115 | addrconf_dad_start(ifp, 0); |
@@ -2134,7 +2177,7 @@ ipv6_inherit_linklocal(struct inet6_dev *idev, struct net_device *link_dev) | |||
2134 | { | 2177 | { |
2135 | struct in6_addr lladdr; | 2178 | struct in6_addr lladdr; |
2136 | 2179 | ||
2137 | if (!ipv6_get_lladdr(link_dev, &lladdr)) { | 2180 | if (!ipv6_get_lladdr(link_dev, &lladdr, IFA_F_TENTATIVE)) { |
2138 | addrconf_add_linklocal(idev, &lladdr); | 2181 | addrconf_add_linklocal(idev, &lladdr); |
2139 | return 0; | 2182 | return 0; |
2140 | } | 2183 | } |
@@ -2479,7 +2522,11 @@ static void addrconf_dad_kick(struct inet6_ifaddr *ifp) | |||
2479 | unsigned long rand_num; | 2522 | unsigned long rand_num; |
2480 | struct inet6_dev *idev = ifp->idev; | 2523 | struct inet6_dev *idev = ifp->idev; |
2481 | 2524 | ||
2482 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | 2525 | if (ifp->flags & IFA_F_OPTIMISTIC) |
2526 | rand_num = 0; | ||
2527 | else | ||
2528 | rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); | ||
2529 | |||
2483 | ifp->probes = idev->cnf.dad_transmits; | 2530 | ifp->probes = idev->cnf.dad_transmits; |
2484 | addrconf_mod_timer(ifp, AC_DAD, rand_num); | 2531 | addrconf_mod_timer(ifp, AC_DAD, rand_num); |
2485 | } | 2532 | } |
@@ -2501,7 +2548,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2501 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2548 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2502 | !(ifp->flags&IFA_F_TENTATIVE) || | 2549 | !(ifp->flags&IFA_F_TENTATIVE) || |
2503 | ifp->flags & IFA_F_NODAD) { | 2550 | ifp->flags & IFA_F_NODAD) { |
2504 | ifp->flags &= ~IFA_F_TENTATIVE; | 2551 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); |
2505 | spin_unlock_bh(&ifp->lock); | 2552 | spin_unlock_bh(&ifp->lock); |
2506 | read_unlock_bh(&idev->lock); | 2553 | read_unlock_bh(&idev->lock); |
2507 | 2554 | ||
@@ -2521,6 +2568,14 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2521 | addrconf_dad_stop(ifp); | 2568 | addrconf_dad_stop(ifp); |
2522 | return; | 2569 | return; |
2523 | } | 2570 | } |
2571 | |||
2572 | /* | ||
2573 | * Optimistic nodes can start receiving | ||
2574 | * Frames right away | ||
2575 | */ | ||
2576 | if(ifp->flags & IFA_F_OPTIMISTIC) | ||
2577 | ip6_ins_rt(ifp->rt); | ||
2578 | |||
2524 | addrconf_dad_kick(ifp); | 2579 | addrconf_dad_kick(ifp); |
2525 | spin_unlock_bh(&ifp->lock); | 2580 | spin_unlock_bh(&ifp->lock); |
2526 | out: | 2581 | out: |
@@ -2545,7 +2600,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2545 | * DAD was successful | 2600 | * DAD was successful |
2546 | */ | 2601 | */ |
2547 | 2602 | ||
2548 | ifp->flags &= ~IFA_F_TENTATIVE; | 2603 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); |
2549 | spin_unlock_bh(&ifp->lock); | 2604 | spin_unlock_bh(&ifp->lock); |
2550 | read_unlock_bh(&idev->lock); | 2605 | read_unlock_bh(&idev->lock); |
2551 | 2606 | ||
@@ -3364,6 +3419,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
3364 | #endif | 3419 | #endif |
3365 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; | 3420 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; |
3366 | array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route; | 3421 | array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route; |
3422 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
3423 | array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad; | ||
3424 | #endif | ||
3367 | } | 3425 | } |
3368 | 3426 | ||
3369 | static inline size_t inet6_if_nlmsg_size(void) | 3427 | static inline size_t inet6_if_nlmsg_size(void) |
@@ -3578,7 +3636,14 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
3578 | 3636 | ||
3579 | switch (event) { | 3637 | switch (event) { |
3580 | case RTM_NEWADDR: | 3638 | case RTM_NEWADDR: |
3581 | ip6_ins_rt(ifp->rt); | 3639 | /* |
3640 | * If the address was optimistic | ||
3641 | * we inserted the route at the start of | ||
3642 | * our DAD process, so we don't need | ||
3643 | * to do it again | ||
3644 | */ | ||
3645 | if (!(ifp->rt->rt6i_node)) | ||
3646 | ip6_ins_rt(ifp->rt); | ||
3582 | if (ifp->idev->cnf.forwarding) | 3647 | if (ifp->idev->cnf.forwarding) |
3583 | addrconf_join_anycast(ifp); | 3648 | addrconf_join_anycast(ifp); |
3584 | break; | 3649 | break; |
@@ -3899,6 +3964,17 @@ static struct addrconf_sysctl_table | |||
3899 | .mode = 0644, | 3964 | .mode = 0644, |
3900 | .proc_handler = &proc_dointvec, | 3965 | .proc_handler = &proc_dointvec, |
3901 | }, | 3966 | }, |
3967 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | ||
3968 | { | ||
3969 | .ctl_name = CTL_UNNUMBERED, | ||
3970 | .procname = "optimistic_dad", | ||
3971 | .data = &ipv6_devconf.optimistic_dad, | ||
3972 | .maxlen = sizeof(int), | ||
3973 | .mode = 0644, | ||
3974 | .proc_handler = &proc_dointvec, | ||
3975 | |||
3976 | }, | ||
3977 | #endif | ||
3902 | { | 3978 | { |
3903 | .ctl_name = 0, /* sentinel */ | 3979 | .ctl_name = 0, /* sentinel */ |
3904 | } | 3980 | } |