cvs commit: src/sys/netinet in_gif.c
SUZUKI Shinsuke
suz at crl.hitachi.co.jp
Mon Dec 6 23:18:03 PST 2004
>>>>> On Mon, 6 Dec 2004 19:02:43 +0000 (UTC)
>>>>> glebius at 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?
-------------- next part --------------
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
More information about the cvs-all
mailing list