cleanup cloned route when parent route (RTF_CLONING) goes away.

adds rt_parent to link parent from child (like NRL did, ours do refcnt
rt_refcnt properly).

bsdi rt_walkbranch would speedup the processing, but since the code will not
be visited too frequently, the current code (with rt_walktree) should be okay.
This commit is contained in:
itojun 2001-01-27 10:39:33 +00:00
parent cd938b3400
commit 02adaaf197
2 changed files with 49 additions and 2 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: route.c,v 1.40 2001/01/27 04:49:31 itojun Exp $ */
/* $NetBSD: route.c,v 1.41 2001/01/27 10:39:33 itojun Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -138,6 +138,8 @@ struct pool rttimer_pool; /* pool for rttimer structures */
struct callout rt_timer_ch; /* callout for rt_timer_timer() */
static int rtdeletemsg __P((struct rtentry *));
static int rtflushit __P((struct radix_node *, void *));
static void rtflushclone __P((struct radix_node_head *, struct rtentry *));
void
rtable_init(table)
@ -403,6 +405,35 @@ rtdeletemsg(rt)
return (error);
}
static int
rtflushit(rn, arg)
struct radix_node *rn;
void *arg;
{
struct rtentry *rt, *parent;
rt = (struct rtentry *)rn;
parent = (struct rtentry *)arg;
if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent == parent)
rtdeletemsg(rt);
return 0;
}
static void
rtflushclone(rnh, parent)
struct radix_node_head *rnh;
struct rtentry *parent;
{
#ifdef DIAGNOSTIC
if (!parent || (parent->rt_flags & RTF_CLONING) == 0)
panic("rtflushclone: called with a non-cloning route");
if (!rnh->rnh_walktree)
panic("rtflushclone: no rnh_walktree");
#endif
rnh->rnh_walktree(rnh, rtflushit, (void *)parent);
}
/*
* Routing table ioctl interface.
*/
@ -547,6 +578,13 @@ rtrequest1(req, info, ret_nrt)
netmask = 0;
switch (req) {
case RTM_DELETE:
if ((rn = rnh->rnh_lookup(dst, netmask, rnh)) == 0)
senderr(ESRCH);
rt = (struct rtentry *)rn;
if ((rt->rt_flags & RTF_CLONING) != 0) {
/* clean up any cloned children */
rtflushclone(rnh, rt);
}
if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0)
senderr(ESRCH);
if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
@ -606,6 +644,8 @@ rtrequest1(req, info, ret_nrt)
rt->rt_ifp = ifa->ifa_ifp;
if (req == RTM_RESOLVE) {
rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
rt->rt_parent = *ret_nrt;
rt->rt_parent->rt_refcnt++;
} else if (rt->rt_rmx.rmx_mtu == 0
&& !(rt->rt_rmx.rmx_locks & RTV_MTU)) { /* XXX */
if (rt->rt_gwroute != NULL) {
@ -627,6 +667,8 @@ rtrequest1(req, info, ret_nrt)
}
if (rn == 0) {
IFAFREE(ifa);
if ((rt->rt_flags & RTF_CLONED) != 0 && rt->rt_parent)
rtfree(rt->rt_parent);
if (rt->rt_gwroute)
rtfree(rt->rt_gwroute);
Free(rt_key(rt));
@ -639,6 +681,10 @@ rtrequest1(req, info, ret_nrt)
*ret_nrt = rt;
rt->rt_refcnt++;
}
if ((rt->rt_flags & RTF_CLONING) != 0) {
/* clean up any cloned children */
rtflushclone(rnh, rt);
}
break;
}
bad:

View File

@ -1,4 +1,4 @@
/* $NetBSD: route.h,v 1.25 2001/01/27 04:49:34 itojun Exp $ */
/* $NetBSD: route.h,v 1.26 2001/01/27 10:39:33 itojun Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@ -109,6 +109,7 @@ struct rtentry {
struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */
struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */
struct rtentry *rt_parent; /* parent of cloned route */
};
/*