summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2009-02-01 21:11:08 +0000
committerbz <bz@FreeBSD.org>2009-02-01 21:11:08 +0000
commit5d8f0a53a75aefe97721f737758596bf3b542e2c (patch)
treea5470a3738df362d49e1bb6da8886ec0f93e4d7c
parent23001c70f6bbdc9d9fdf1e5004247a1ca399bca0 (diff)
downloadFreeBSD-src-5d8f0a53a75aefe97721f737758596bf3b542e2c.zip
FreeBSD-src-5d8f0a53a75aefe97721f737758596bf3b542e2c.tar.gz
Remove the single global unlocked route cache ip6_forward_rt
from the inet6 stack along with statistics and make sure we properly free the rt in all cases. While the current situation is not better performance wise it prevents panics seen more often these days. After more inet6 and ipsec cleanup we should be able to improve the situation again passing the rt to ip6_forward directly. Leave the ip6_forward_rt entry in struct vinet6 but mark it for removal. PR: kern/128247, kern/131038 MFC after: 25 days Committed from: Bugathon #6 Tested by: Denis Ahrens <denis@h3q.com> (different initial version)
-rw-r--r--UPDATING4
-rw-r--r--sys/netinet6/frag6.c12
-rw-r--r--sys/netinet6/ip6_forward.c107
-rw-r--r--sys/netinet6/ip6_input.c80
-rw-r--r--sys/netinet6/ip6_var.h3
-rw-r--r--sys/netinet6/vinet6.h3
-rw-r--r--usr.bin/netstat/inet6.c2
7 files changed, 75 insertions, 136 deletions
diff --git a/UPDATING b/UPDATING
index 04d0c17..d8d0b0e 100644
--- a/UPDATING
+++ b/UPDATING
@@ -22,6 +22,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW:
to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
+20090201:
+ INET6 statistics (struct ip6stat) was updated.
+ netstat(1) needs to be recompiled.
+
20090119:
NTFS has been removed from GENERIC kernel on amd64 to match
GENERIC on i386. Should not cause any issues since mount_ntfs(8)
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index b63e23c..e2eda6f 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -751,18 +751,6 @@ frag6_slowtimo(void)
}
VNET_LIST_RUNLOCK();
IP6Q_UNLOCK();
-
-#if 0
- /*
- * Routing changes might produce a better route than we last used;
- * make sure we notice eventually, even if forwarding only for one
- * destination and the cache is never replaced.
- */
- if (V_ip6_forward_rt.ro_rt) {
- RTFREE(V_ip6_forward_rt.ro_rt);
- V_ip6_forward_rt.ro_rt = 0;
- }
-#endif
}
/*
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 0ce591f..ca5101f 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -77,10 +77,6 @@ __FBSDID("$FreeBSD$");
#include <netinet6/ip6protosw.h>
-#ifdef VIMAGE_GLOBALS
-struct route_in6 ip6_forward_rt;
-#endif
-
/*
* Forward a packet. If some error occurs return the sender
* an icmp packet. Note we can't always generate a meaningful
@@ -100,6 +96,7 @@ ip6_forward(struct mbuf *m, int srcrt)
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct sockaddr_in6 *dst = NULL;
struct rtentry *rt = NULL;
+ struct route_in6 rin6;
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
@@ -112,8 +109,6 @@ ip6_forward(struct mbuf *m, int srcrt)
#endif
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
- /* GIANT_REQUIRED; */ /* XXX bz: ip6_forward_rt */
-
#ifdef IPSEC
/*
* Check AH/ESP integrity.
@@ -355,56 +350,27 @@ ip6_forward(struct mbuf *m, int srcrt)
skip_ipsec:
#endif
- dst = (struct sockaddr_in6 *)&V_ip6_forward_rt.ro_dst;
- if (!srcrt) {
- /* ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst */
- if (V_ip6_forward_rt.ro_rt == 0 ||
- (V_ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0) {
- if (V_ip6_forward_rt.ro_rt) {
- RTFREE(V_ip6_forward_rt.ro_rt);
- V_ip6_forward_rt.ro_rt = 0;
- }
-
- /* this probably fails but give it a try again */
- rtalloc((struct route *)&V_ip6_forward_rt);
- }
-
- if (V_ip6_forward_rt.ro_rt == 0) {
- V_ip6stat.ip6s_noroute++;
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
- if (mcopy) {
- icmp6_error(mcopy, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_NOROUTE, 0);
- }
- m_freem(m);
- return;
- }
- } else if ((rt = V_ip6_forward_rt.ro_rt) == 0 ||
- !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr)) {
- if (V_ip6_forward_rt.ro_rt) {
- RTFREE(V_ip6_forward_rt.ro_rt);
- V_ip6_forward_rt.ro_rt = 0;
- }
- bzero(dst, sizeof(*dst));
- dst->sin6_len = sizeof(struct sockaddr_in6);
- dst->sin6_family = AF_INET6;
- dst->sin6_addr = ip6->ip6_dst;
-
- rtalloc((struct route *)&V_ip6_forward_rt);
- if (V_ip6_forward_rt.ro_rt == 0) {
- V_ip6stat.ip6s_noroute++;
- in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
- if (mcopy) {
- icmp6_error(mcopy, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_NOROUTE, 0);
- }
- m_freem(m);
- return;
+ bzero(&rin6, sizeof(struct route_in6));
+ dst = (struct sockaddr_in6 *)&rin6.ro_dst;
+ dst->sin6_len = sizeof(struct sockaddr_in6);
+ dst->sin6_family = AF_INET6;
+ dst->sin6_addr = ip6->ip6_dst;
+
+ rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
+ if (rin6.ro_rt != NULL)
+ RT_UNLOCK(rin6.ro_rt);
+ else {
+ V_ip6stat.ip6s_noroute++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
+ if (mcopy) {
+ icmp6_error(mcopy, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_NOROUTE, 0);
}
+ goto bad;
}
- rt = V_ip6_forward_rt.ro_rt;
+ rt = rin6.ro_rt;
#ifdef IPSEC
- skip_routing:;
+skip_routing:
#endif
/*
@@ -421,14 +387,12 @@ skip_ipsec:
/* XXX: this should not happen */
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
- m_freem(m);
- return;
+ goto bad;
}
if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) {
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
- m_freem(m);
- return;
+ goto bad;
}
if (inzone != outzone
#ifdef IPSEC
@@ -452,8 +416,7 @@ skip_ipsec:
if (mcopy)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
- m_freem(m);
- return;
+ goto bad;
}
/*
@@ -469,8 +432,7 @@ skip_ipsec:
inzone != outzone) {
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
- m_freem(m);
- return;
+ goto bad;
}
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
@@ -510,8 +472,7 @@ skip_ipsec:
#endif /* IPSEC */
icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
}
- m_freem(m);
- return;
+ goto bad;
}
if (rt->rt_flags & RTF_GATEWAY)
@@ -544,8 +505,7 @@ skip_ipsec:
*/
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADDR, 0);
- m_freem(m);
- return;
+ goto bad;
}
type = ND_REDIRECT;
}
@@ -624,12 +584,12 @@ pass:
senderr:
if (mcopy == NULL)
- return;
+ goto out;
switch (error) {
case 0:
if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt);
- return;
+ goto out;
}
goto freecopy;
@@ -651,9 +611,18 @@ senderr:
break;
}
icmp6_error(mcopy, type, code, 0);
- return;
+ goto out;
freecopy:
m_freem(mcopy);
- return;
+ goto out;
+bad:
+ m_freem(m);
+out:
+ if (rt != NULL
+#ifdef IPSEC
+ && !ipsecrt
+#endif
+ )
+ RTFREE(rt);
}
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 1aaf0b2..f120ec5 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -143,8 +143,6 @@ extern int icmp6errppslim;
extern int icmp6_nodeinfo;
extern int udp6_sendspace;
extern int udp6_recvspace;
-
-extern struct route_in6 ip6_forward_rt;
#endif
struct pfil_head inet6_pfil_hook;
@@ -309,10 +307,12 @@ ip6_input(struct mbuf *m)
int nxt, ours = 0;
struct ifnet *deliverifp = NULL, *ifp = NULL;
struct in6_addr odst;
+ struct route_in6 rin6;
int srcrt = 0;
struct llentry *lle = NULL;
- struct sockaddr_in6 dst6;
+ struct sockaddr_in6 dst6, *dst;
+ bzero(&rin6, sizeof(struct route_in6));
#ifdef IPSEC
/*
* should the inner packet be considered authentic?
@@ -565,29 +565,13 @@ passin:
if (lle != NULL)
LLE_RUNLOCK(lle);
- if (V_ip6_forward_rt.ro_rt != NULL &&
- (V_ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
- IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
- &((struct sockaddr_in6 *)(&V_ip6_forward_rt.ro_dst))->sin6_addr))
- V_ip6stat.ip6s_forward_cachehit++;
- else {
- struct sockaddr_in6 *dst6;
-
- if (V_ip6_forward_rt.ro_rt) {
- /* route is down or destination is different */
- V_ip6stat.ip6s_forward_cachemiss++;
- RTFREE(V_ip6_forward_rt.ro_rt);
- V_ip6_forward_rt.ro_rt = 0;
- }
-
- bzero(&V_ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
- dst6 = (struct sockaddr_in6 *)&V_ip6_forward_rt.ro_dst;
- dst6->sin6_len = sizeof(struct sockaddr_in6);
- dst6->sin6_family = AF_INET6;
- dst6->sin6_addr = ip6->ip6_dst;
-
- rtalloc((struct route *)&V_ip6_forward_rt);
- }
+ dst = &rin6.ro_dst;
+ dst->sin6_len = sizeof(struct sockaddr_in6);
+ dst->sin6_family = AF_INET6;
+ dst->sin6_addr = ip6->ip6_dst;
+ rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
+ if (rin6.ro_rt)
+ RT_UNLOCK(rin6.ro_rt);
#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
@@ -611,14 +595,14 @@ passin:
* while it would be less efficient. Or, should we rather install a
* reject route for such a case?
*/
- if (V_ip6_forward_rt.ro_rt &&
- (V_ip6_forward_rt.ro_rt->rt_flags &
+ if (rin6.ro_rt &&
+ (rin6.ro_rt->rt_flags &
(RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
#ifdef RTF_WASCLONED
- !(V_ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
+ !(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
#endif
#ifdef RTF_CLONED
- !(V_ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
+ !(rin6.ro_rt->rt_flags & RTF_CLONED) &&
#endif
#if 0
/*
@@ -627,11 +611,11 @@ passin:
* already done through looking up the routing table.
*/
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
- &rt6_key(V_ip6_forward_rt.ro_rt)->sin6_addr)
+ &rt6_key(rin6.ro_rt)->sin6_addr)
#endif
- V_ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
+ rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
struct in6_ifaddr *ia6 =
- (struct in6_ifaddr *)V_ip6_forward_rt.ro_rt->rt_ifa;
+ (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
/*
* record address information into m_tag.
@@ -667,11 +651,11 @@ passin:
* FAITH (Firewall Aided Internet Translator)
*/
if (V_ip6_keepfaith) {
- if (V_ip6_forward_rt.ro_rt && V_ip6_forward_rt.ro_rt->rt_ifp
- && V_ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
+ if (rin6.ro_rt && rin6.ro_rt->rt_ifp &&
+ rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) {
/* XXX do we need more sanity checks? */
ours = 1;
- deliverifp = V_ip6_forward_rt.ro_rt->rt_ifp; /* faith */
+ deliverifp = rin6.ro_rt->rt_ifp; /* faith */
goto hbhcheck;
}
}
@@ -721,7 +705,7 @@ passin:
#if 0 /*touches NULL pointer*/
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
#endif
- return; /* m have already been freed */
+ goto out; /* m have already been freed */
}
/* adjust pointer */
@@ -744,7 +728,7 @@ passin:
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
(caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
- return;
+ goto out;
}
#ifndef PULLDOWN_TEST
/* ip6_hopopts_input() ensures that mbuf is contiguous */
@@ -754,7 +738,7 @@ passin:
sizeof(struct ip6_hbh));
if (hbh == NULL) {
V_ip6stat.ip6s_tooshort++;
- return;
+ goto out;
}
#endif
nxt = hbh->ip6h_nxt;
@@ -816,16 +800,13 @@ passin:
if (ip6_mrouter && ip6_mforward &&
ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
V_ip6stat.ip6s_cantforward++;
- m_freem(m);
- return;
- }
- if (!ours) {
- m_freem(m);
- return;
+ goto bad;
}
+ if (!ours)
+ goto bad;
} else if (!ours) {
ip6_forward(m, srcrt);
- return;
+ goto out;
}
ip6 = mtod(m, struct ip6_hdr *);
@@ -880,9 +861,12 @@ passin:
#endif /* IPSEC */
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
}
- return;
- bad:
+ goto out;
+bad:
m_freem(m);
+out:
+ if (rin6.ro_rt)
+ RTFREE(rin6.ro_rt);
}
/*
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 00b19a7..9e8476c 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -229,9 +229,6 @@ struct ip6stat {
/* number of times that a deprecated address is chosen */
u_quad_t ip6s_sources_deprecated[16];
- u_quad_t ip6s_forward_cachehit;
- u_quad_t ip6s_forward_cachemiss;
-
/* number of times that each rule of source selection is applied. */
u_quad_t ip6s_sources_rule[16];
};
diff --git a/sys/netinet6/vinet6.h b/sys/netinet6/vinet6.h
index e67f731..e0a1fa0 100644
--- a/sys/netinet6/vinet6.h
+++ b/sys/netinet6/vinet6.h
@@ -54,7 +54,7 @@ struct vnet_inet6 {
u_int _frag6_nfrags;
struct ip6q _ip6q;
- struct route_in6 _ip6_forward_rt;
+ struct route_in6 _ip6_forward_rt; /* XXX remove */
struct in6_addrpolicy _defaultaddrpolicy;
TAILQ_HEAD(, addrsel_policyent) _addrsel_policytab;
@@ -194,7 +194,6 @@ extern struct vnet_inet6 vnet_inet6_0;
#define V_ip6_defhlim VNET_INET6(ip6_defhlim)
#define V_ip6_defmcasthlim VNET_INET6(ip6_defmcasthlim)
#define V_ip6_desync_factor VNET_INET6(ip6_desync_factor)
-#define V_ip6_forward_rt VNET_INET6(ip6_forward_rt)
#define V_ip6_forwarding VNET_INET6(ip6_forwarding)
#define V_ip6_hdrnestlimit VNET_INET6(ip6_hdrnestlimit)
#define V_ip6_keepfaith VNET_INET6(ip6_keepfaith)
diff --git a/usr.bin/netstat/inet6.c b/usr.bin/netstat/inet6.c
index b4aeb1a0..83a31c7f 100644
--- a/usr.bin/netstat/inet6.c
+++ b/usr.bin/netstat/inet6.c
@@ -512,8 +512,6 @@ ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
}
}
- p1a(ip6s_forward_cachehit, "\t%ju forward cache hit\n");
- p1a(ip6s_forward_cachemiss, "\t%ju forward cache miss\n");
printf("\tSource addresses selection rule applied:\n");
for (i = 0; i < 16; i++) {
if (ip6stat.ip6s_sources_rule[i])
OpenPOWER on IntegriCloud