Date: Tue, 07 Dec 2004 14:03:02 +0900 From: SUZUKI Shinsuke <suz@crl.hitachi.co.jp> To: glebius@FreeBSD.org Cc: cvs-all@FreeBSD.org Subject: Re: cvs commit: src/sys/netinet in_gif.c Message-ID: <x7fz2i7la1.wl%suz@crl.hitachi.co.jp> In-Reply-To: <200412061902.iB6J2hJ6000543@repoman.freebsd.org> References: <200412061902.iB6J2hJ6000543@repoman.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--Multipart_Tue_Dec__7_14:03:02_2004-1 Content-Type: text/plain; charset=US-ASCII >>>>> On Mon, 6 Dec 2004 19:02:43 +0000 (UTC) >>>>> glebius@FreeBSD.org(Gleb Smirnoff) said: > - Make route cacheing optional, configurable via IFF_LINK0 flag. > - Turn it off by default. > Revision Changes Path > 1.27 +6 -0 src/sys/netinet/in_gif.c Three comments, and one proposal. - please comment this change in share/man/man4/gif.4 - you need the same fix to sys/netinet6/in6_gif.c (for IPv4 over IPv6 tunnel) - it seems like sys/net/if_stf.c also needs the similar fix (I haven't confirmed it though, I'll check it later) - Here's a patch to update route cache periodically, to prevent unexpected gif failure due to a stale route cache. Is it okay to commit it together with your change? --Multipart_Tue_Dec__7_14:03:02_2004-1 Content-Type: text/plain; charset=US-ASCII Index: net/if_gif.h =================================================================== RCS file: /home/ncvs/src/sys/net/if_gif.h,v retrieving revision 1.15 diff -u -u -r1.15 if_gif.h --- net/if_gif.h 5 Apr 2004 16:55:15 -0000 1.15 +++ net/if_gif.h 7 Dec 2004 04:53:39 -0000 @@ -70,6 +70,7 @@ const struct encaptab *encap_cookie6; void *gif_netgraph; /* ng_gif(4) netgraph node info */ LIST_ENTRY(gif_softc) gif_list; /* all gif's are linked */ + time_t rtcache_expire; /* expiration time of the cached route */ }; #define gif_ro gifsc_gifscr.gifscr_ro Index: netinet/in_gif.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_gif.c,v retrieving revision 1.27 diff -u -u -r1.27 in_gif.c --- netinet/in_gif.c 6 Dec 2004 19:02:43 -0000 1.27 +++ netinet/in_gif.c 7 Dec 2004 04:53:39 -0000 @@ -83,6 +83,7 @@ }; static int ip_gif_ttl = GIF_TTL; +static int in_gif_rtcachettl = 300; /* XXX appropriate value? configurable? */ SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW, &ip_gif_ttl, 0, ""); @@ -99,6 +100,7 @@ struct ip iphdr; /* capsule IP header, host byte ordered */ int proto, error; u_int8_t tos; + struct timeval mono_time; if (sin_src == NULL || sin_dst == NULL || sin_src->sin_family != AF_INET || @@ -174,23 +176,38 @@ } bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); - if (dst->sin_family != sin_dst->sin_family || - dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) { - /* cache route doesn't match */ - bzero(dst, sizeof(*dst)); - dst->sin_family = sin_dst->sin_family; - dst->sin_len = sizeof(struct sockaddr_in); - dst->sin_addr = sin_dst->sin_addr; - if (sc->gif_ro.ro_rt) { - RTFREE(sc->gif_ro.ro_rt); - sc->gif_ro.ro_rt = NULL; - } + microtime(&mono_time); + + /* + * Check if the cached route is still valid. If not, create another + * one. + * XXX: we should be able to let ip_output() to validate the cache + * and to make a new route (see in6_gif_output()). However, FreeBSD's + * ip_output() does not make a clone for the new route, while we'd + * like do so in case of route changes. Thus, we reluctantly put + * almost duplicated logic here. + */ + if (sc->gif_ro.ro_rt && (!(sc->gif_ro.ro_rt->rt_flags & RTF_UP) || + dst->sin_family != sin_dst->sin_family || + dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr || + sc->rtcache_expire == 0 || mono_time.tv_sec >= sc->rtcache_expire)) { + /* + * The cache route doesn't match, has been invalidated, or has + * expired. + */ + RTFREE(sc->gif_ro.ro_rt); + sc->gif_ro.ro_rt = NULL; #if 0 sc->gif_if.if_mtu = GIF_MTU; #endif } if (sc->gif_ro.ro_rt == NULL) { + bzero(dst, sizeof(*dst)); + dst->sin_family = sin_dst->sin_family; + dst->sin_len = sizeof(struct sockaddr_in); + dst->sin_addr = sin_dst->sin_addr; + rtalloc_ign(&sc->gif_ro, 0); if (sc->gif_ro.ro_rt == NULL) { m_freem(m); @@ -199,9 +216,13 @@ /* if it constitutes infinite encapsulation, punt. */ if (sc->gif_ro.ro_rt->rt_ifp == ifp) { + RTFREE(sc->gif_ro.ro_rt); + sc->gif_ro.ro_rt = NULL; m_freem(m); return ENETUNREACH; /* XXX */ } + + sc->rtcache_expire = mono_time.tv_sec + in_gif_rtcachettl; #if 0 ifp->if_mtu = sc->gif_ro.ro_rt->rt_ifp->if_mtu - sizeof(struct ip); Index: netinet6/in6_gif.c =================================================================== RCS file: /home/ncvs/src/sys/netinet6/in6_gif.c,v retrieving revision 1.16 diff -u -u -r1.16 in6_gif.c --- netinet6/in6_gif.c 29 Oct 2003 15:07:04 -0000 1.16 +++ netinet6/in6_gif.c 7 Dec 2004 04:53:39 -0000 @@ -72,6 +72,7 @@ static int gif_validate6(const struct ip6_hdr *, struct gif_softc *, struct ifnet *); +static int in6_gif_rtcachettl = 300; /* XXX see in_gif.c */ extern struct domain inet6domain; struct ip6protosw in6_gif_protosw = @@ -93,8 +94,9 @@ struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc; struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst; struct ip6_hdr *ip6; - int proto; + int proto, error; u_int8_t itos, otos; + struct timeval mono_time; if (sin6_src == NULL || sin6_dst == NULL || sin6_src->sin6_family != AF_INET6 || @@ -173,23 +175,24 @@ ip6->ip6_flow &= ~htonl(0xff << 20); ip6->ip6_flow |= htonl((u_int32_t)otos << 20); - if (dst->sin6_family != sin6_dst->sin6_family || - !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) { + microtime(&mono_time); + + if (sc->gif_ro6.ro_rt && (dst->sin6_family != sin6_dst->sin6_family || + !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr) || + sc->rtcache_expire == 0 || mono_time.tv_sec >= sc->rtcache_expire)) { /* cache route doesn't match */ - bzero(dst, sizeof(*dst)); - dst->sin6_family = sin6_dst->sin6_family; - dst->sin6_len = sizeof(struct sockaddr_in6); - dst->sin6_addr = sin6_dst->sin6_addr; - if (sc->gif_ro6.ro_rt) { - RTFREE(sc->gif_ro6.ro_rt); - sc->gif_ro6.ro_rt = NULL; - } + RTFREE(sc->gif_ro6.ro_rt); + sc->gif_ro6.ro_rt = NULL; #if 0 sc->gif_if.if_mtu = GIF_MTU; #endif } if (sc->gif_ro6.ro_rt == NULL) { + bzero(dst, sizeof(*dst)); + dst->sin6_family = sin6_dst->sin6_family; + dst->sin6_len = sizeof(struct sockaddr_in6); + dst->sin6_addr = sin6_dst->sin6_addr; rtalloc((struct route *)&sc->gif_ro6); if (sc->gif_ro6.ro_rt == NULL) { m_freem(m); @@ -198,6 +201,8 @@ /* if it constitutes infinite encapsulation, punt. */ if (sc->gif_ro.ro_rt->rt_ifp == ifp) { + sc->gif_ro6.ro_rt = NULL; + RTFREE(sc->gif_ro6.ro_rt); m_freem(m); return ENETUNREACH; /*XXX*/ } @@ -213,10 +218,19 @@ * it is too painful to ask for resend of inner packet, to achieve * path MTU discovery for encapsulated packets. */ - return (ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL, NULL)); + error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL, NULL); #else - return (ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL, NULL)); + error = ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL, NULL); #endif + + /* + * if a (new) cached route has been created in ip6_output(), extend + * the expiration time. + */ + if (sc->gif_ro6.ro_rt && mono_time.tv_sec >= sc->rtcache_expire) + sc->rtcache_expire = mono_time.tv_sec + in6_gif_rtcachettl; + + return (error); } int --Multipart_Tue_Dec__7_14:03:02_2004-1--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?x7fz2i7la1.wl%suz>