Skip to content

Commit c757faa

Browse files
tracywwnjdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b16cb45 commit c757faa

File tree

4 files changed

+84
-17
lines changed

4 files changed

+84
-17
lines changed

include/net/ip6_fib.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929
#define FIB6_TABLE_HASHSZ 1
3030
#endif
3131

32+
#define RT6_DEBUG 2
33+
34+
#if RT6_DEBUG >= 3
35+
#define RT6_TRACE(x...) pr_debug(x)
36+
#else
37+
#define RT6_TRACE(x...) do { ; } while (0)
38+
#endif
39+
3240
struct rt6_info;
3341

3442
struct fib6_config {
@@ -75,6 +83,11 @@ struct fib6_node {
7583
struct rcu_head rcu;
7684
};
7785

86+
struct fib6_gc_args {
87+
int timeout;
88+
int more;
89+
};
90+
7891
#ifndef CONFIG_IPV6_SUBTREES
7992
#define FIB6_SUBTREE(fn) NULL
8093
#else

include/net/ip6_route.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ int ip6_del_rt(struct rt6_info *);
9797

9898
void rt6_flush_exceptions(struct rt6_info *rt);
9999
int rt6_remove_exception_rt(struct rt6_info *rt);
100+
void rt6_age_exceptions(struct rt6_info *rt, struct fib6_gc_args *gc_args,
101+
unsigned long now);
100102

101103
static inline int ip6_route_get_saddr(struct net *net, struct rt6_info *rt,
102104
const struct in6_addr *daddr,

net/ipv6/ip6_fib.c

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,6 @@
3838
#include <net/ip6_fib.h>
3939
#include <net/ip6_route.h>
4040

41-
#define RT6_DEBUG 2
42-
43-
#if RT6_DEBUG >= 3
44-
#define RT6_TRACE(x...) pr_debug(x)
45-
#else
46-
#define RT6_TRACE(x...) do { ; } while (0)
47-
#endif
48-
4941
static struct kmem_cache *fib6_node_kmem __read_mostly;
5042

5143
struct fib6_cleaner {
@@ -1890,12 +1882,6 @@ static void fib6_flush_trees(struct net *net)
18901882
* Garbage collection
18911883
*/
18921884

1893-
struct fib6_gc_args
1894-
{
1895-
int timeout;
1896-
int more;
1897-
};
1898-
18991885
static int fib6_age(struct rt6_info *rt, void *arg)
19001886
{
19011887
struct fib6_gc_args *gc_args = arg;
@@ -1904,9 +1890,6 @@ static int fib6_age(struct rt6_info *rt, void *arg)
19041890
/*
19051891
* check addrconf expiration here.
19061892
* Routes are expired even if they are in use.
1907-
*
1908-
* Also age clones. Note, that clones are aged out
1909-
* only if they are not in use now.
19101893
*/
19111894

19121895
if (rt->rt6i_flags & RTF_EXPIRES && rt->dst.expires) {
@@ -1915,6 +1898,9 @@ static int fib6_age(struct rt6_info *rt, void *arg)
19151898
return -1;
19161899
}
19171900
gc_args->more++;
1901+
/* The following part will soon be removed when the exception
1902+
* table is hooked up to store all cached routes.
1903+
*/
19181904
} else if (rt->rt6i_flags & RTF_CACHE) {
19191905
if (time_after_eq(now, rt->dst.lastuse + gc_args->timeout))
19201906
rt->dst.obsolete = DST_OBSOLETE_KILL;
@@ -1940,6 +1926,12 @@ static int fib6_age(struct rt6_info *rt, void *arg)
19401926
gc_args->more++;
19411927
}
19421928

1929+
/* Also age clones in the exception table.
1930+
* Note, that clones are aged out
1931+
* only if they are not in use now.
1932+
*/
1933+
rt6_age_exceptions(rt, gc_args, now);
1934+
19431935
return 0;
19441936
}
19451937

net/ipv6/route.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,66 @@ static void rt6_exceptions_clean_tohost(struct rt6_info *rt,
15281528
spin_unlock_bh(&rt6_exception_lock);
15291529
}
15301530

1531+
static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
1532+
struct rt6_exception *rt6_ex,
1533+
struct fib6_gc_args *gc_args,
1534+
unsigned long now)
1535+
{
1536+
struct rt6_info *rt = rt6_ex->rt6i;
1537+
1538+
if (atomic_read(&rt->dst.__refcnt) == 1 &&
1539+
time_after_eq(now, rt->dst.lastuse + gc_args->timeout)) {
1540+
RT6_TRACE("aging clone %p\n", rt);
1541+
rt6_remove_exception(bucket, rt6_ex);
1542+
return;
1543+
} else if (rt->rt6i_flags & RTF_GATEWAY) {
1544+
struct neighbour *neigh;
1545+
__u8 neigh_flags = 0;
1546+
1547+
neigh = dst_neigh_lookup(&rt->dst, &rt->rt6i_gateway);
1548+
if (neigh) {
1549+
neigh_flags = neigh->flags;
1550+
neigh_release(neigh);
1551+
}
1552+
if (!(neigh_flags & NTF_ROUTER)) {
1553+
RT6_TRACE("purging route %p via non-router but gateway\n",
1554+
rt);
1555+
rt6_remove_exception(bucket, rt6_ex);
1556+
return;
1557+
}
1558+
}
1559+
gc_args->more++;
1560+
}
1561+
1562+
void rt6_age_exceptions(struct rt6_info *rt,
1563+
struct fib6_gc_args *gc_args,
1564+
unsigned long now)
1565+
{
1566+
struct rt6_exception_bucket *bucket;
1567+
struct rt6_exception *rt6_ex;
1568+
struct hlist_node *tmp;
1569+
int i;
1570+
1571+
if (!rcu_access_pointer(rt->rt6i_exception_bucket))
1572+
return;
1573+
1574+
spin_lock_bh(&rt6_exception_lock);
1575+
bucket = rcu_dereference_protected(rt->rt6i_exception_bucket,
1576+
lockdep_is_held(&rt6_exception_lock));
1577+
1578+
if (bucket) {
1579+
for (i = 0; i < FIB6_EXCEPTION_BUCKET_SIZE; i++) {
1580+
hlist_for_each_entry_safe(rt6_ex, tmp,
1581+
&bucket->chain, hlist) {
1582+
rt6_age_examine_exception(bucket, rt6_ex,
1583+
gc_args, now);
1584+
}
1585+
bucket++;
1586+
}
1587+
}
1588+
spin_unlock_bh(&rt6_exception_lock);
1589+
}
1590+
15311591
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
15321592
int oif, struct flowi6 *fl6, int flags)
15331593
{

0 commit comments

Comments
 (0)