Hello.
I'm sorry for taking last minutes. Please pull the following changesets and push them to the 2.6.15 queue. These fix, basically, random "FAIL"s in IPv6 Ready Logo Phase-2 Self Test in IPv6 Core Protocols. Changesets are available at: git://git.skbuff.net/gitroot/yoshfuji/linux-2.6.14+git+ipv6-fix-20051221a FYI, test results of the IPv6 Ready Logo Phase-2 IPv6 Core Protocols with these changesets are available at: Host: http://altair.linux-ipv6.org/v6eval.1/ct-v6logo2-20051221a/ Router: http://altair.linux-ipv6.org/v6eval.2/ct-v6logo2-20051221a/ And, one more rebase, please... (We will convert your work-queue if requested.) Thank you. Regarads, HEADLINES --------- [IPV6]: Flag RTF_ANYCAST for anycast routes. [IPV6]: Try not to send icmp to anycast address. [IPV6]: Defer IPv6 device initialization until the link becomes ready. [IPV6]: Run DAD when the link becomes ready. [IPV6]: Don't select a tentative address as a source address. DIFFSTAT -------- include/linux/ipv6_route.h | 1 include/net/if_inet6.h | 1 net/ipv6/addrconf.c | 106 +++++++++++++++++++++++++++++++++++++++----- net/ipv6/icmp.c | 16 ++++++- net/ipv6/route.c | 13 ++++- 5 files changed, 120 insertions(+), 17 deletions(-) CHANGESETS ---------- diff-tree 58c4fb86eabcbc385d954843a635b7f4327be6b0 (from bb44f116a14c4c932f15c79acfafd46bcb43ca9a) Author: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> Date: Wed Dec 21 22:56:42 2005 +0900 [IPV6]: Flag RTF_ANYCAST for anycast routes. Signed-off-by: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h index e2f9350..d7c41d1 100644 --- a/include/linux/ipv6_route.h +++ b/include/linux/ipv6_route.h @@ -18,6 +18,7 @@ fallback, no routers on link */ #define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ #define RTF_PREFIX_RT 0x00080000 /* A prefix only route - RA */ +#define RTF_ANYCAST 0x00100000 /* Anycast */ #define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ #define RTF_EXPIRES 0x00400000 diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7c68bfb..66140f1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -413,11 +413,14 @@ static struct rt6_info *rt6_cow(struct r rt = ip6_rt_copy(ort); if (rt) { - ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); - - if (!(rt->rt6i_flags&RTF_GATEWAY)) + if (!(rt->rt6i_flags&RTF_GATEWAY)) { + if (rt->rt6i_dst.plen != 128 && + ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) + rt->rt6i_flags |= RTF_ANYCAST; ipv6_addr_copy(&rt->rt6i_gateway, daddr); + } + ipv6_addr_copy(&rt->rt6i_dst.addr, daddr); rt->rt6i_dst.plen = 128; rt->rt6i_flags |= RTF_CACHE; rt->u.dst.flags |= DST_HOST; @@ -1413,7 +1416,9 @@ struct rt6_info *addrconf_dst_alloc(stru rt->u.dst.obsolete = -1; rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; - if (!anycast) + if (anycast) + rt->rt6i_flags |= RTF_ANYCAST; + else rt->rt6i_flags |= RTF_LOCAL; rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); if (rt->rt6i_nexthop == NULL) { --- diff-tree 8de3351e6e0a1081fbf6864ae37839e327699a08 (from 58c4fb86eabcbc385d954843a635b7f4327be6b0) Author: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> Date: Wed Dec 21 22:57:06 2005 +0900 [IPV6]: Try not to send icmp to anycast address. Signed-off-by: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 34a3322..6ec6a2b 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -328,8 +328,10 @@ void icmpv6_send(struct sk_buff *skb, in iif = skb->dev->ifindex; /* - * Must not send if we know that source is Anycast also. - * for now we don't know that. + * Must not send error if the source does not uniquely + * identify a single node (RFC2463 Section 2.4). + * We check unspecified / multicast addresses here, + * and anycast addresses will be checked later. */ if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"); @@ -373,6 +375,16 @@ void icmpv6_send(struct sk_buff *skb, in err = ip6_dst_lookup(sk, &dst, &fl); if (err) goto out; + + /* + * We won't send icmp if the destination is known + * anycast. + */ + if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { + LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); + goto out_dst_release; + } + if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) goto out; --- diff-tree 3c21edbd113788b110116141c8078623a0900b6a (from 8de3351e6e0a1081fbf6864ae37839e327699a08) Author: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> Date: Wed Dec 21 22:57:24 2005 +0900 [IPV6]: Defer IPv6 device initialization until the link becomes ready. NETDEV_UP might be sent even if the link attached to the interface was not ready. DAD does not make sense in such case, so we won't do so. After interface Signed-off-by: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index e97a9ac..d8234f9 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -24,6 +24,7 @@ #define IF_RA_MANAGED 0x40 #define IF_RA_RCVD 0x20 #define IF_RS_SENT 0x10 +#define IF_READY 0x80000000 /* prefix flags */ #define IF_PREFIX_ONLINK 0x01 diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4ea8cf7..d012f6a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -388,6 +388,9 @@ static struct inet6_dev * ipv6_add_dev(s } #endif + if (netif_carrier_ok(dev)) + ndev->if_flags |= IF_READY; + write_lock_bh(&addrconf_lock); dev->ip6_ptr = ndev; write_unlock_bh(&addrconf_lock); @@ -1215,10 +1218,8 @@ int ipv6_rcv_saddr_equal(const struct so /* Gets referenced address, destroys ifaddr */ -void addrconf_dad_failure(struct inet6_ifaddr *ifp) +void addrconf_dad_stop(struct inet6_ifaddr *ifp) { - if (net_ratelimit()) - printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); if (ifp->flags&IFA_F_PERMANENT) { spin_lock_bh(&ifp->lock); addrconf_del_timer(ifp); @@ -1244,6 +1245,12 @@ void addrconf_dad_failure(struct inet6_i ipv6_del_addr(ifp); } +void addrconf_dad_failure(struct inet6_ifaddr *ifp) +{ + if (net_ratelimit()) + printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); + addrconf_dad_stop(ifp); +} /* Join to solicited addr multicast group. */ @@ -2136,6 +2143,37 @@ static int addrconf_notify(struct notifi switch(event) { case NETDEV_UP: + case NETDEV_CHANGE: + if (event == NETDEV_UP) { + if (!netif_carrier_ok(dev)) { + /* device is not ready yet. */ + printk(KERN_INFO + "ADDRCONF(NETDEV_UP): %s: " + "link is not ready\n", + dev->name); + break; + } + } else { + if (!netif_carrier_ok(dev)) { + /* device is still not ready. */ + break; + } + + if (idev) { + if (idev->if_flags & IF_READY) { + /* device is already configured. */ + break; + } + idev->if_flags |= IF_READY; + } + + printk(KERN_INFO + "ADDRCONF(NETDEV_CHANGE): %s: " + "link becomes ready\n", + dev->name); + + } + switch(dev->type) { case ARPHRD_SIT: addrconf_sit_config(dev); @@ -2186,8 +2224,7 @@ static int addrconf_notify(struct notifi */ addrconf_ifdown(dev, event != NETDEV_DOWN); break; - case NETDEV_CHANGE: - break; + case NETDEV_CHANGENAME: #ifdef CONFIG_SYSCTL if (idev) { @@ -2268,7 +2305,7 @@ static int addrconf_ifdown(struct net_de /* Step 3: clear flags for stateless addrconf */ if (how != 1) - idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD); + idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); /* Step 4: clear address list */ #ifdef CONFIG_IPV6_PRIVACY @@ -2377,11 +2414,20 @@ out: /* * Duplicate Address Detection */ +static void addrconf_dad_kick(struct inet6_ifaddr *ifp) +{ + unsigned long rand_num; + struct inet6_dev *idev = ifp->idev; + + rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); + ifp->probes = idev->cnf.dad_transmits; + addrconf_mod_timer(ifp, AC_DAD, rand_num); +} + static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) { struct inet6_dev *idev = ifp->idev; struct net_device *dev = idev->dev; - unsigned long rand_num; addrconf_join_solict(dev, &ifp->addr); @@ -2390,7 +2436,6 @@ static void addrconf_dad_start(struct in flags); net_srandom(ifp->addr.s6_addr32[3]); - rand_num = net_random() % (idev->cnf.rtr_solicit_delay ? : 1); read_lock_bh(&idev->lock); if (ifp->dead) @@ -2407,8 +2452,17 @@ static void addrconf_dad_start(struct in return; } - ifp->probes = idev->cnf.dad_transmits; - addrconf_mod_timer(ifp, AC_DAD, rand_num); + if (idev->if_flags & IF_READY) + addrconf_dad_kick(ifp); + else { + /* + * If the defice is not ready: + * - keep it tentative if it is a permanent address. + * - otherwise, kill it. + */ + in6_ifa_hold(ifp); + addrconf_dad_stop(ifp); + } spin_unlock_bh(&ifp->lock); out: --- diff-tree c5e33bddd3c798f681f8f3027270127be6b61a3b (from 3c21edbd113788b110116141c8078623a0900b6a) Author: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> Date: Wed Dec 21 22:57:44 2005 +0900 [IPV6]: Run DAD when the link becomes ready. If the link was not available when the interface was created, run DAD for pending tentative addresses when the link becomes ready. Signed-off-by: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d012f6a..f6ead6a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -137,6 +137,7 @@ static int addrconf_ifdown(struct net_de static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); static void addrconf_dad_timer(unsigned long data); static void addrconf_dad_completed(struct inet6_ifaddr *ifp); +static void addrconf_dad_run(struct inet6_dev *idev); static void addrconf_rs_timer(unsigned long data); static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); @@ -418,6 +419,7 @@ static struct inet6_dev * ipv6_find_idev if ((idev = ipv6_add_dev(dev)) == NULL) return NULL; } + if (dev->flags&IFF_UP) ipv6_mc_up(idev); return idev; @@ -2140,6 +2142,7 @@ static int addrconf_notify(struct notifi { struct net_device *dev = (struct net_device *) data; struct inet6_dev *idev = __in6_dev_get(dev); + int run_pending = 0; switch(event) { case NETDEV_UP: @@ -2172,6 +2175,7 @@ static int addrconf_notify(struct notifi "link becomes ready\n", dev->name); + run_pending = 1; } switch(dev->type) { @@ -2190,6 +2194,9 @@ static int addrconf_notify(struct notifi break; }; if (idev) { + if (run_pending) + addrconf_dad_run(idev); + /* If the MTU changed during the interface down, when the interface up, the changed MTU must be reflected in the idev as well as routers. @@ -2546,6 +2553,22 @@ static void addrconf_dad_completed(struc } } +static void addrconf_dad_run(struct inet6_dev *idev) { + struct inet6_ifaddr *ifp; + + read_lock_bh(&idev->lock); + for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { + spin_lock_bh(&ifp->lock); + if (!(ifp->flags & IFA_F_TENTATIVE)) { + spin_unlock_bh(&ifp->lock); + continue; + } + spin_unlock_bh(&ifp->lock); + addrconf_dad_kick(ifp); + } + read_unlock_bh(&idev->lock); +} + #ifdef CONFIG_PROC_FS struct if6_iter_state { int bucket; --- diff-tree 6b3ae80a63e47f6e97d68a1ddd520e3509e62821 (from c5e33bddd3c798f681f8f3027270127be6b61a3b) Author: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> Date: Wed Dec 21 22:58:01 2005 +0900 [IPV6]: Don't select a tentative address as a source address. A tentative address is not considered "assigned to an interface" in the traditional sense (RFC2462 Section 4). Don't try to select such an address for the source address. Signed-off-by: YOSHIFUJI Hideaki <[EMAIL PROTECTED]> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f6ead6a..fd03c39 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -908,11 +908,18 @@ int ipv6_dev_get_saddr(struct net_device score.addr_type = __ipv6_addr_type(&ifa->addr); - /* Rule 0: Candidate Source Address (section 4) + /* Rule 0: + * - Tentative Address (RFC2462 section 5.4) + * - A tentative address is not considered + * "assigned to an interface" in the traditional + * sense. + * - Candidate Source Address (section 4) * - In any case, anycast addresses, multicast * addresses, and the unspecified address MUST * NOT be included in a candidate set. */ + if (ifa->flags & IFA_F_TENTATIVE) + continue; if (unlikely(score.addr_type == IPV6_ADDR_ANY || score.addr_type & IPV6_ADDR_MULTICAST)) { LIMIT_NETDEBUG(KERN_DEBUG --- -- YOSHIFUJI Hideaki @ USAGI Project <[EMAIL PROTECTED]> GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html