ipv6: prepare fib6_age() for exception table
If all dst cache entries are stored in the exception table under the main route, we have to go through them during fib6_age() when doing garbage collecting. Introduce a new function rt6_age_exception() which goes through all dst entries in the exception table and remove those entries that are expired. This function is called in fib6_age() so that all dst caches are also garbage collected. Signed-off-by: Wei Wang <weiwan@google.com> Signed-off-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
b16cb459d7
commit
c757faa8bf
@@ -1528,6 +1528,66 @@ static void rt6_exceptions_clean_tohost(struct rt6_info *rt,
|
||||
spin_unlock_bh(&rt6_exception_lock);
|
||||
}
|
||||
|
||||
static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
|
||||
struct rt6_exception *rt6_ex,
|
||||
struct fib6_gc_args *gc_args,
|
||||
unsigned long now)
|
||||
{
|
||||
struct rt6_info *rt = rt6_ex->rt6i;
|
||||
|
||||
if (atomic_read(&rt->dst.__refcnt) == 1 &&
|
||||
time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
|
||||
RT6_TRACE("aging clone %p\n", rt);
|
||||
rt6_remove_exception(bucket, rt6_ex);
|
||||
return;
|
||||
} else if (rt->rt6i_flags & RTF_GATEWAY) {
|
||||
struct neighbour *neigh;
|
||||
__u8 neigh_flags = 0;
|
||||
|
||||
neigh = dst_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
|
||||
if (neigh) {
|
||||
neigh_flags = neigh->flags;
|
||||
neigh_release(neigh);
|
||||
}
|
||||
if (!(neigh_flags & NTF_ROUTER)) {
|
||||
RT6_TRACE("purging route %p via non-router but gateway\n",
|
||||
rt);
|
||||
rt6_remove_exception(bucket, rt6_ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
gc_args->more++;
|
||||
}
|
||||
|
||||
void rt6_age_exceptions(struct rt6_info *rt,
|
||||
struct fib6_gc_args *gc_args,
|
||||
unsigned long now)
|
||||
{
|
||||
struct rt6_exception_bucket *bucket;
|
||||
struct rt6_exception *rt6_ex;
|
||||
struct hlist_node *tmp;
|
||||
int i;
|
||||
|
||||
if (!rcu_access_pointer(rt->rt6i_exception_bucket))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&rt6_exception_lock);
|
||||
bucket = rcu_dereference_protected(rt->rt6i_exception_bucket,
|
||||
lockdep_is_held(&rt6_exception_lock));
|
||||
|
||||
if (bucket) {
|
||||
for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) {
|
||||
hlist_for_each_entry_safe(rt6_ex, tmp,
|
||||
&bucket->chain, hlist) {
|
||||
rt6_age_examine_exception(bucket, rt6_ex,
|
||||
gc_args, now);
|
||||
}
|
||||
bucket++;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&rt6_exception_lock);
|
||||
}
|
||||
|
||||
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
||||
int oif, struct flowi6 *fl6, int flags)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user