HI Vlad, > -----Original Message----- > From: Vlad Yasevich [mailto:[EMAIL PROTECTED] > Sent: Tuesday, November 13, 2007 7:51 AM > To: Templin, Fred L > Cc: netdev@vger.kernel.org; YOSHIFUJI Hideaki / 吉藤英明 > Subject: Re: [PATCH 01/01] ipv6: RFC4214 Support (v2.0) > > Hi Fred > > Some comments. > > Templin, Fred L wrote: > > From: Fred L. Templin <[EMAIL PROTECTED]> > > > > This patch includes support for the Intra-Site Automatic Tunnel > > Addressing Protocol (ISATAP) per RFC4214. It uses the SIT > > module, and is configured using extensions to the "iproute2" > > utility. > > > > The following diffs are specific to the Linux 2.6.24-rc2 kernel > > distribution. This message includes the full and patchable > diff text; > > please use this version to apply patches. > > > > Signed-off-by: Fred L. Templin <[EMAIL PROTECTED]> > > > > --- > > > > --- linux-2.6.24-rc2/include/linux/if.h.orig > 2007-11-08 12:05:47.000000000 -0800 > > +++ linux-2.6.24-rc2/include/linux/if.h 2007-11-08 > 08:26:44.000000000 -0800 > > @@ -61,6 +61,7 @@ > > #define IFF_MASTER_ALB 0x10 /* bonding > master, balance-alb. */ > > #define IFF_BONDING 0x20 /* bonding > master or slave */ > > #define IFF_SLAVE_NEEDARP 0x40 /* need ARPs > for validation */ > > +#define IFF_ISATAP 0x80 /* ISATAP interface > (RFC4214) */ > > > > #define IF_GET_IFACE 0x0001 /* for querying only */ > > #define IF_GET_PROTO 0x0002 > > --- linux-2.6.24-rc2/include/linux/in.h.orig > 2007-11-09 08:00:32.000000000 -0800 > > +++ linux-2.6.24-rc2/include/linux/in.h 2007-11-12 > 07:37:05.000000000 -0800 > > @@ -253,6 +253,14 @@ struct sockaddr_in { > > #define ZERONET(x) (((x) & htonl(0xff000000)) == htonl(0x00000000)) > > #define LOCAL_MCAST(x) (((x) & htonl(0xFFFFFF00)) == > htonl(0xE0000000)) > > > > +/* Special-Use IPv4 Addresses (RFC3330) */ > > +#define PRIVATE_10(x) (((x) & htonl(0xff000000)) == > htonl(0x0A000000)) > > +#define LINKLOCAL_169(x) (((x) & htonl(0xffff0000)) == > htonl(0xA9FE0000)) > > +#define PRIVATE_172(x) (((x) & htonl(0xfff00000)) == > htonl(0xAC100000)) > > +#define TEST_192(x) (((x) & htonl(0xffffff00)) == > htonl(0xC0000200)) > > +#define ANYCAST_6TO4(x) (((x) & htonl(0xffffff00)) == > htonl(0xC0586300)) > > +#define PRIVATE_192(x) (((x) & htonl(0xffff0000)) == > htonl(0xC0A80000)) > > +#define TEST_198(x) (((x) & htonl(0xfffe0000)) == > htonl(0xC6120000)) > > #endif > > > > #endif /* _LINUX_IN_H */ > > --- linux-2.6.24-rc2/include/net/addrconf.h.orig > 2007-11-08 12:06:17.000000000 -0800 > > +++ linux-2.6.24-rc2/include/net/addrconf.h 2007-11-12 > 14:29:51.000000000 -0800 > > @@ -241,6 +241,12 @@ static inline int ipv6_addr_is_ll_all_ro > > addr->s6_addr32[3] == htonl(0x00000002)); > > } > > > > +/* only for IFF_ISATAP interfaces */ > > +static inline int ipv6_addr_is_isatap(const struct in6_addr *addr) > > +{ > > + return ((addr->s6_addr32[2] | htonl(0x02000000)) == > htonl(0x02005EFE)); > > +} > > + > > #ifdef CONFIG_PROC_FS > > extern int if6_proc_init(void); > > extern void if6_proc_exit(void); > > --- linux-2.6.24-rc2/net/ipv6/addrconf.c.orig > 2007-11-08 11:59:35.000000000 -0800 > > +++ linux-2.6.24-rc2/net/ipv6/addrconf.c 2007-11-12 > 14:32:43.000000000 -0800 > > @@ -75,7 +75,7 @@ > > #include <net/ip.h> > > #include <net/netlink.h> > > #include <net/pkt_sched.h> > > -#include <linux/if_tunnel.h> > > +#include <net/ipip.h> > > #include <linux/rtnetlink.h> > > > > #ifdef CONFIG_IPV6_PRIVACY > > @@ -1424,6 +1424,20 @@ static int addrconf_ifid_infiniband(u8 * > > return 0; > > } > > > > +static int addrconf_ifid_isatap(u8 *eui, __be32 addr) > > +{ > > + > > + eui[0] = 0x02; eui[1] = 0; eui[2] = 0x5E; eui[3] = 0xFE; > > + memcpy (eui+4, &addr, 4); > > + > > + if (ZERONET(addr) || PRIVATE_10(addr) || LOOPBACK(addr) || > > + LINKLOCAL_169(addr) || PRIVATE_172(addr) || > TEST_192(addr) || > > + ANYCAST_6TO4(addr) || PRIVATE_192(addr) || TEST_198(addr) || > > + MULTICAST(addr) || BADCLASS(addr)) eui[0] &= ~0x02; > > Please put the assignment on its own line.
OK. > > + > > + return 0; > > +} > > + > > static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) > > { > > switch (dev->type) { > > @@ -1435,6 +1449,9 @@ static int ipv6_generate_eui64(u8 *eui, > > return addrconf_ifid_arcnet(eui, dev); > > case ARPHRD_INFINIBAND: > > return addrconf_ifid_infiniband(eui, dev); > > + case ARPHRD_SIT: > > + if (dev->priv_flags & IFF_ISATAP) > > + return addrconf_ifid_isatap(eui, > *(__be32 *)dev->dev_addr); > > } > > return -1; > > } > > @@ -1470,8 +1487,7 @@ regen: > > * > > * - Reserved subnet anycast (RFC 2526) > > * 11111101 11....11 1xxxxxxx > > - * - ISATAP (draft-ietf-ngtrans-isatap-13.txt) 5.1 > > - * 00-00-5E-FE-xx-xx-xx-xx > > + * - ISATAP (RFC4214) 00-00-5E-FE-xx-xx-xx-xx > > * - value 0 > > * - XXX: already assigned to an address on the device > > */ > > @@ -2201,6 +2217,29 @@ static void addrconf_sit_config(struct n > > return; > > } > > > > + /* ISATAP (RFC4214) - NBMA link */ > > + if (dev->priv_flags & IFF_ISATAP) { > > + struct in6_addr addr; > > + > > + addrconf_add_lroute(dev); > > + > > + ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); > > + > > + if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0) { > > + struct inet6_ifaddr *ifp; > > + > > + ifp = ipv6_add_addr(idev, &addr, 64, > > + IFA_LINK, IFA_F_PERMANENT); > > + if (!IS_ERR(ifp)) { > > + addrconf_prefix_route(&ifp->addr, > > + ifp->prefix_len, > idev->dev, 0, 0); > > + addrconf_dad_start(ifp, 0); > > + in6_ifa_put(ifp); > > + } > > + > > If ipv6_generate_eui64() or ipv6_add_addr() fail, you will > still have a link-local > prefix route on the device. > > You might want to pull out the above code into a separate > function and do correct > clean-ups on failures. OK. > > + return; > > + } > > + > > sit_add_v4_addrs(idev); > > > > if (dev->flags&IFF_POINTOPOINT) { > > @@ -2531,6 +2570,18 @@ static void addrconf_rs_timer(unsigned l > > * Announcement received after solicitation > > * was sent > > */ > > + > > + /* ISATAP (RFC4214) - schedule next RS/RA */ > > + if (ifp->idev->dev->priv_flags & IFF_ISATAP) { > > + struct ip_tunnel *t = > netdev_priv(ifp->idev->dev); > > + if (t->parms.i_key != INADDR_NONE) { > > + spin_lock(&ifp->lock); > > + ifp->probes = 0; > > + ifp->idev->if_flags &= > ~(IF_RS_SENT|IF_RA_RCVD); > > + addrconf_mod_timer(ifp, AC_DAD, > t->parms.o_key*HZ); > > You are using a DAD timer to schedule RS? I am using the DAD timer to re-DAD the link local, which in turn schedules RS. > > + spin_unlock(&ifp->lock); > > + } > > + } > > goto out; > > } > > > > @@ -2545,10 +2596,28 @@ static void addrconf_rs_timer(unsigned l > > ifp->idev->cnf.rtr_solicit_interval); > > spin_unlock(&ifp->lock); > > > > - ipv6_addr_all_routers(&all_routers); > > + /* ISATAP (RFC4214) - unicast RS */ > > + if (ifp->idev->dev->priv_flags & IFF_ISATAP) { > > + struct ip_tunnel *t = > netdev_priv(ifp->idev->dev); > > + > > + if (t->parms.i_key == INADDR_NONE) goto out; > > + > > + ipv6_addr_set(&all_routers, > htonl(0xFE800000), 0, 0, 0); > > + > addrconf_ifid_isatap(all_routers.s6_addr + 8, t->parms.i_key); > > + } else > > + ipv6_addr_all_routers(&all_routers); > > > > ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); > > } else { > > + /* ISATAP (RFC4214) - try again later */ > > + if (ifp->idev->dev->priv_flags & IFF_ISATAP) { > > + struct ip_tunnel *t = > netdev_priv(ifp->idev->dev); > > + if (t->parms.i_key != INADDR_NONE) { > > + ifp->probes = 0; > > + ifp->idev->if_flags &= > ~(IF_RS_SENT|IF_RA_RCVD); > > + addrconf_mod_timer(ifp, AC_DAD, > t->parms.o_key*HZ); > > Again, using DAD timer? Same as above. > > + } > > + } > > spin_unlock(&ifp->lock); > > /* > > * Note: we do not support deprecated "all on-link" > > @@ -2594,6 +2663,7 @@ static void addrconf_dad_start(struct in > > spin_lock_bh(&ifp->lock); > > > > if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || > > + dev->priv_flags&IFF_ISATAP || > > !(ifp->flags&IFA_F_TENTATIVE) || > > ifp->flags & IFA_F_NODAD) { > > ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); > > @@ -2690,7 +2760,16 @@ static void addrconf_dad_completed(struc > > (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { > > struct in6_addr all_routers; > > > > - ipv6_addr_all_routers(&all_routers); > > + /* ISATAP (RFC4214) - unicast RS */ > > + if (ifp->idev->dev->priv_flags & IFF_ISATAP) { > > + struct ip_tunnel *t = > netdev_priv(ifp->idev->dev); > > + > > + if (t->parms.i_key == INADDR_NONE) return; > > + > > + ipv6_addr_set(&all_routers, > htonl(0xFE800000), 0, 0, 0); > > + > addrconf_ifid_isatap(all_routers.s6_addr + 8, t->parms.i_key); > > + } else > > + ipv6_addr_all_routers(&all_routers); > > > > /* > > * If a host as already performed a random delay > > --- linux-2.6.24-rc2/net/ipv6/sit.c.orig 2007-11-08 > 12:03:41.000000000 -0800 > > +++ linux-2.6.24-rc2/net/ipv6/sit.c 2007-11-12 > 14:30:52.000000000 -0800 > > @@ -16,6 +16,7 @@ > > * Changes: > > * Roger Venning <[EMAIL PROTECTED]>: 6to4 support > > * Nate Thompson <[EMAIL PROTECTED]>: 6to4 support > > + * Fred L. Templin <[EMAIL PROTECTED]>: isatap support > > */ > > > > #include <linux/module.h> > > @@ -182,6 +183,8 @@ static struct ip_tunnel * ipip6_tunnel_l > > dev->init = ipip6_tunnel_init; > > nt->parms = *parms; > > > > + if (parms->i_key) dev->priv_flags |= IFF_ISATAP; > > + > > if (register_netdevice(dev) < 0) { > > free_netdev(dev); > > goto failed; > > @@ -382,6 +385,47 @@ static int ipip6_rcv(struct sk_buff *skb > > IPCB(skb)->flags = 0; > > skb->protocol = htons(ETH_P_IPV6); > > skb->pkt_type = PACKET_HOST; > > + > > + /* ISATAP (RFC4214) - check source address */ > > + if (tunnel->dev->priv_flags & IFF_ISATAP) { > > + struct neighbour *neigh; > > + struct dst_entry *dst; > > + struct flowi fl; > > + struct in6_addr *addr6; > > + struct ipv6hdr *iph6; > > + > > + /* from ISATAP router */ > > + if ((tunnel->parms.i_key != INADDR_NONE) && > > + (iph->saddr == > tunnel->parms.i_key)) goto accept; > > + > > + iph6 = ipv6_hdr(skb); > > + addr6 = &iph6->saddr; > > + > > + /* from legitimate previous hop */ > > + memset(&fl, 0, sizeof(fl)); > > + fl.proto = iph6->nexthdr; > > + ipv6_addr_copy(&fl.fl6_dst, addr6); > > + fl.oif = tunnel->dev->ifindex; > > + security_skb_classify_flow(skb, &fl); > > + > > + if (!(dst = ip6_route_output(NULL, &fl)) || > > + (dst->dev != tunnel->dev) || > > + ((neigh = dst->neighbour) == > NULL)) goto drop; > > You are catching the error conditions incorrectly. > ip6_route_output will return > a pointer to dst whose error field will be set if the route > lookup failed. You need > to do something like: > dst = ip6_route_output(NULL, &fl); > if (dst->error || dst->dev != > tunnel->dev || ...) OK. > Also, please put the 'goto' on its own line. OK. > > + > > + addr6 = (struct in6_addr*)&neigh->primary_key; > > + > > + if (!(ipv6_addr_is_isatap(addr6)) || > > + (addr6->s6_addr32[3] != iph->saddr)) { > > +drop: > > + tunnel->stat.rx_errors++; > > + read_unlock(&ipip6_lock); > > + dst_release(dst); > > + kfree_skb(skb); > > + return 0; > > + } > > + dst_release(dst); > > + } > > +accept: > > You never use the 'drop' or 'accept' tags. You can remove > them. OK. > Also, it appears > that you are doing some validations on the tunnel. Might > want to split that out into its > own function and just call that. OK. Fred [EMAIL PROTECTED] > -vlad > > > tunnel->stat.rx_packets++; > > tunnel->stat.rx_bytes += skb->len; > > skb->dev = tunnel->dev; > > @@ -444,6 +488,29 @@ static int ipip6_tunnel_xmit(struct sk_b > > if (skb->protocol != htons(ETH_P_IPV6)) > > goto tx_error; > > > > + /* ISATAP (RFC4214) - must come before 6to4 */ > > + if (dev->priv_flags & IFF_ISATAP) { > > + struct neighbour *neigh = NULL; > > + > > + if (skb->dst) > > + neigh = skb->dst->neighbour; > > + > > + if (neigh == NULL) { > > + if (net_ratelimit()) > > + printk(KERN_DEBUG "sit: nexthop > == NULL\n"); > > + goto tx_error; > > + } > > + > > + addr6 = (struct in6_addr*)&neigh->primary_key; > > + addr_type = ipv6_addr_type(addr6); > > + > > + if ((addr_type & IPV6_ADDR_UNICAST) && > > + ipv6_addr_is_isatap(addr6)) > > + dst = addr6->s6_addr32[3]; > > + else > > + goto tx_error; > > + } > > + > > if (!dst) > > dst = try_6to4(&iph6->daddr); > > > > @@ -651,6 +718,8 @@ ipip6_tunnel_ioctl (struct net_device *d > > ipip6_tunnel_unlink(t); > > t->parms.iph.saddr = p.iph.saddr; > > t->parms.iph.daddr = p.iph.daddr; > > + t->parms.i_key = p.i_key; > > + t->parms.o_key = p.o_key; > > memcpy(dev->dev_addr, &p.iph.saddr, 4); > > memcpy(dev->broadcast, &p.iph.daddr, 4); > > ipip6_tunnel_link(t); > > @@ -663,6 +732,8 @@ ipip6_tunnel_ioctl (struct net_device *d > > if (cmd == SIOCCHGTUNNEL) { > > t->parms.iph.ttl = p.iph.ttl; > > t->parms.iph.tos = p.iph.tos; > > + t->parms.i_key = p.i_key; > > + t->parms.o_key = p.o_key; > > } > > if > (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p))) > > err = -EFAULT; > > - > > 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 > > > > - 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