Don't call rtcache_check() from the fast-forward code, which runs
at IPL_NET, because rtcache_check() may read the forwarding table. Elsewhere, the kernel only blocks interrupts at priority IPL_SOFTNET and below while it modifies the forwarding table, so rtcache_check() could be reading the table in an inconsistent state. Use rtcache_done(), instead. XXX netinet/ip_flow.c and netinet6/ip6_flow.c are virtually identical. XXX They should share code.
This commit is contained in:
parent
1ee8b50f43
commit
bd98464c6f
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip_flow.c,v 1.47 2007/05/02 22:39:04 dyoung Exp $ */
|
||||
/* $NetBSD: ip_flow.c,v 1.48 2007/08/20 19:42:34 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.47 2007/05/02 22:39:04 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.48 2007/08/20 19:42:34 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -220,9 +220,8 @@ ipflow_fastforward(struct mbuf *m)
|
||||
/*
|
||||
* Route and interface still up?
|
||||
*/
|
||||
rtcache_check(&ipf->ipf_ro);
|
||||
rt = ipf->ipf_ro.ro_rt;
|
||||
if (rt == NULL || (rt->rt_ifp->if_flags & IFF_UP) == 0)
|
||||
if (rtcache_down(&ipf->ipf_ro) || (rt = ipf->ipf_ro.ro_rt) == NULL ||
|
||||
(rt->rt_ifp->if_flags & IFF_UP) == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -293,8 +292,7 @@ ipflow_fastforward(struct mbuf *m)
|
||||
static void
|
||||
ipflow_addstats(struct ipflow *ipf)
|
||||
{
|
||||
rtcache_check(&ipf->ipf_ro);
|
||||
if (ipf->ipf_ro.ro_rt != NULL)
|
||||
if (!rtcache_down(&ipf->ipf_ro) && ipf->ipf_ro.ro_rt != NULL)
|
||||
ipf->ipf_ro.ro_rt->rt_use += ipf->ipf_uses;
|
||||
ipstat.ips_cantforward += ipf->ipf_errors + ipf->ipf_dropped;
|
||||
ipstat.ips_total += ipf->ipf_uses;
|
||||
@ -335,8 +333,8 @@ ipflow_reap(int just_one)
|
||||
* If this no longer points to a valid route
|
||||
* reclaim it.
|
||||
*/
|
||||
rtcache_check(&ipf->ipf_ro);
|
||||
if (ipf->ipf_ro.ro_rt == NULL)
|
||||
if (rtcache_down(&ipf->ipf_ro) ||
|
||||
ipf->ipf_ro.ro_rt == NULL)
|
||||
goto done;
|
||||
/*
|
||||
* choose the one that's been least recently
|
||||
@ -377,9 +375,8 @@ ipflow_slowtimo(void)
|
||||
|
||||
for (ipf = LIST_FIRST(&ipflowlist); ipf != NULL; ipf = next_ipf) {
|
||||
next_ipf = LIST_NEXT(ipf, ipf_list);
|
||||
rtcache_check(&ipf->ipf_ro);
|
||||
if (PRT_SLOW_ISEXPIRED(ipf->ipf_timer) ||
|
||||
ipf->ipf_ro.ro_rt == NULL) {
|
||||
rtcache_down(&ipf->ipf_ro) || ipf->ipf_ro.ro_rt == NULL) {
|
||||
ipflow_free(ipf);
|
||||
} else {
|
||||
ipf->ipf_last_uses = ipf->ipf_uses;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ip6_flow.c,v 1.8 2007/05/02 22:39:04 dyoung Exp $ */
|
||||
/* $NetBSD: ip6_flow.c,v 1.9 2007/08/20 19:42:34 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
@ -268,9 +268,9 @@ ip6flow_fastforward(struct mbuf *m)
|
||||
/*
|
||||
* Route and interface still up?
|
||||
*/
|
||||
rtcache_check(&ip6f->ip6f_ro);
|
||||
rt = ip6f->ip6f_ro.ro_rt;
|
||||
if (rt == NULL || (rt->rt_ifp->if_flags & IFF_UP) == 0) {
|
||||
if (rtcache_down(&ip6f->ip6f_ro) ||
|
||||
(rt = ip6f->ip6f_ro.ro_rt) == NULL ||
|
||||
(rt->rt_ifp->if_flags & IFF_UP) == 0) {
|
||||
/* Route or interface is down */
|
||||
return 0;
|
||||
}
|
||||
@ -314,8 +314,7 @@ ip6flow_fastforward(struct mbuf *m)
|
||||
static void
|
||||
ip6flow_addstats(struct ip6flow *ip6f)
|
||||
{
|
||||
rtcache_check(&ip6f->ip6f_ro);
|
||||
if (ip6f->ip6f_ro.ro_rt != NULL)
|
||||
if (!rtcache_down(&ip6f->ip6f_ro) && ip6f->ip6f_ro.ro_rt != NULL)
|
||||
ip6f->ip6f_ro.ro_rt->rt_use += ip6f->ip6f_uses;
|
||||
ip6stat.ip6s_fastforwardflows = ip6flow_inuse;
|
||||
ip6stat.ip6s_cantforward += ip6f->ip6f_dropped;
|
||||
@ -364,8 +363,8 @@ ip6flow_reap(int just_one)
|
||||
* If this no longer points to a valid route -
|
||||
* reclaim it.
|
||||
*/
|
||||
rtcache_check(&ip6f->ip6f_ro);
|
||||
if (ip6f->ip6f_ro.ro_rt == NULL)
|
||||
if (rtcache_down(&ip6f->ip6f_ro) ||
|
||||
ip6f->ip6f_ro.ro_rt == NULL)
|
||||
goto done;
|
||||
/*
|
||||
* choose the one that's been least recently
|
||||
@ -408,8 +407,8 @@ ip6flow_slowtimo(void)
|
||||
|
||||
for (ip6f = LIST_FIRST(&ip6flowlist); ip6f != NULL; ip6f = next_ip6f) {
|
||||
next_ip6f = LIST_NEXT(ip6f, ip6f_list);
|
||||
rtcache_check(&ip6f->ip6f_ro);
|
||||
if (PRT_SLOW_ISEXPIRED(ip6f->ip6f_timer) ||
|
||||
rtcache_down(&ip6f->ip6f_ro) ||
|
||||
ip6f->ip6f_ro.ro_rt == NULL) {
|
||||
ip6flow_free(ip6f);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user