Skip to content

Commit

Permalink
[IPV6]: Multiple Routing Tables
Browse files Browse the repository at this point in the history
Adds the framework to support multiple IPv6 routing tables.
Currently all automatically generated routes are put into the
same table. This could be changed at a later point after
considering the produced locking overhead.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Thomas Graf authored and David S. Miller committed Sep 22, 2006
1 parent 5d0bbee commit c71099a
Show file tree
Hide file tree
Showing 6 changed files with 441 additions and 137 deletions.
39 changes: 38 additions & 1 deletion include/net/ip6_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct rt6key
int plen;
};

struct fib6_table;

struct rt6_info
{
union {
Expand All @@ -71,6 +73,7 @@ struct rt6_info
u32 rt6i_flags;
u32 rt6i_metric;
atomic_t rt6i_ref;
struct fib6_table *rt6i_table;

struct rt6key rt6i_dst;
struct rt6key rt6i_src;
Expand Down Expand Up @@ -143,12 +146,43 @@ struct rt6_statistics {

typedef void (*f_pnode)(struct fib6_node *fn, void *);

extern struct fib6_node ip6_routing_table;
struct fib6_table {
struct hlist_node tb6_hlist;
u32 tb6_id;
rwlock_t tb6_lock;
struct fib6_node tb6_root;
};

#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC
#define RT6_TABLE_MAIN RT_TABLE_MAIN
#define RT6_TABLE_LOCAL RT6_TABLE_MAIN
#define RT6_TABLE_DFLT RT6_TABLE_MAIN
#define RT6_TABLE_INFO RT6_TABLE_MAIN
#define RT6_TABLE_PREFIX RT6_TABLE_MAIN

#ifdef CONFIG_IPV6_MULTIPLE_TABLES
#define FIB6_TABLE_MIN 1
#define FIB6_TABLE_MAX RT_TABLE_MAX
#else
#define FIB6_TABLE_MIN RT_TABLE_MAIN
#define FIB6_TABLE_MAX FIB6_TABLE_MIN
#endif

#define RT6_F_STRICT 1
#define RT6_F_HAS_SADDR 2

typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *,
struct flowi *, int);

/*
* exported functions
*/

extern struct fib6_table * fib6_get_table(u32 id);
extern struct fib6_table * fib6_new_table(u32 id);
extern struct dst_entry * fib6_rule_lookup(struct flowi *fl, int flags,
pol_lookup_t lookup);

extern struct fib6_node *fib6_lookup(struct fib6_node *root,
struct in6_addr *daddr,
struct in6_addr *saddr);
Expand All @@ -161,6 +195,9 @@ extern void fib6_clean_tree(struct fib6_node *root,
int (*func)(struct rt6_info *, void *arg),
int prune, void *arg);

extern void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
int prune, void *arg);

extern int fib6_walk(struct fib6_walker_t *w);
extern int fib6_walk_continue(struct fib6_walker_t *w);

Expand Down
3 changes: 2 additions & 1 deletion include/net/ip6_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg);
extern int ip6_route_add(struct in6_rtmsg *rtmsg,
struct nlmsghdr *,
void *rtattr,
struct netlink_skb_parms *req);
struct netlink_skb_parms *req,
u32 table_id);
extern int ip6_ins_rt(struct rt6_info *,
struct nlmsghdr *,
void *rtattr,
Expand Down
6 changes: 6 additions & 0 deletions net/ipv6/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,9 @@ config IPV6_TUNNEL

If unsure, say N.

config IPV6_MULTIPLE_TABLES
bool "IPv6: Multiple Routing Tables"
depends on IPV6 && EXPERIMENTAL
---help---
Support multiple routing tables.

6 changes: 3 additions & 3 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
rtmsg.rtmsg_flags |= RTF_NONEXTHOP;

ip6_route_add(&rtmsg, NULL, NULL, NULL);
ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_PREFIX);
}

/* Create "default" multicast route to the interface */
Expand All @@ -1542,7 +1542,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP;
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
ip6_route_add(&rtmsg, NULL, NULL, NULL);
ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_LOCAL);
}

static void sit_route_add(struct net_device *dev)
Expand All @@ -1559,7 +1559,7 @@ static void sit_route_add(struct net_device *dev)
rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
rtmsg.rtmsg_ifindex = dev->ifindex;

ip6_route_add(&rtmsg, NULL, NULL, NULL);
ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_MAIN);
}

static void addrconf_add_lroute(struct net_device *dev)
Expand Down
144 changes: 140 additions & 4 deletions net/ipv6/ip6_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/netdevice.h>
#include <linux/in6.h>
#include <linux/init.h>
#include <linux/list.h>

#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
Expand Down Expand Up @@ -147,6 +148,126 @@ static __inline__ void rt6_release(struct rt6_info *rt)
dst_free(&rt->u.dst);
}

static struct fib6_table fib6_main_tbl = {
.tb6_id = RT6_TABLE_MAIN,
.tb6_lock = RW_LOCK_UNLOCKED,
.tb6_root = {
.leaf = &ip6_null_entry,
.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
},
};

#ifdef CONFIG_IPV6_MULTIPLE_TABLES

#define FIB_TABLE_HASHSZ 256
static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ];

static struct fib6_table *fib6_alloc_table(u32 id)
{
struct fib6_table *table;

table = kzalloc(sizeof(*table), GFP_ATOMIC);
if (table != NULL) {
table->tb6_id = id;
table->tb6_lock = RW_LOCK_UNLOCKED;
table->tb6_root.leaf = &ip6_null_entry;
table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
}

return table;
}

static void fib6_link_table(struct fib6_table *tb)
{
unsigned int h;

h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);

/*
* No protection necessary, this is the only list mutatation
* operation, tables never disappear once they exist.
*/
hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]);
}

struct fib6_table *fib6_new_table(u32 id)
{
struct fib6_table *tb;

if (id == 0)
id = RT6_TABLE_MAIN;
tb = fib6_get_table(id);
if (tb)
return tb;

tb = fib6_alloc_table(id);
if (tb != NULL)
fib6_link_table(tb);

return tb;
}

struct fib6_table *fib6_get_table(u32 id)
{
struct fib6_table *tb;
struct hlist_node *node;
unsigned int h;

if (id == 0)
id = RT6_TABLE_MAIN;
h = id & (FIB_TABLE_HASHSZ - 1);
rcu_read_lock();
hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) {
if (tb->tb6_id == id) {
rcu_read_unlock();
return tb;
}
}
rcu_read_unlock();

return NULL;
}

struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
pol_lookup_t lookup)
{
/*
* TODO: Add rule lookup
*/
struct fib6_table *table = fib6_get_table(RT6_TABLE_MAIN);

return (struct dst_entry *) lookup(table, fl, flags);
}

static void __init fib6_tables_init(void)
{
fib6_link_table(&fib6_main_tbl);
}

#else

struct fib6_table *fib6_new_table(u32 id)
{
return fib6_get_table(id);
}

struct fib6_table *fib6_get_table(u32 id)
{
return &fib6_main_tbl;
}

struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
pol_lookup_t lookup)
{
return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags);
}

static void __init fib6_tables_init(void)
{
}

#endif


/*
* Routing Table
Expand Down Expand Up @@ -1064,6 +1185,22 @@ void fib6_clean_tree(struct fib6_node *root,
fib6_walk(&c.w);
}

void fib6_clean_all(int (*func)(struct rt6_info *, void *arg),
int prune, void *arg)
{
int i;
struct fib6_table *table;

for (i = FIB6_TABLE_MIN; i <= FIB6_TABLE_MAX; i++) {
table = fib6_get_table(i);
if (table != NULL) {
write_lock_bh(&table->tb6_lock);
fib6_clean_tree(&table->tb6_root, func, prune, arg);
write_unlock_bh(&table->tb6_lock);
}
}
}

static int fib6_prune_clone(struct rt6_info *rt, void *arg)
{
if (rt->rt6i_flags & RTF_CACHE) {
Expand Down Expand Up @@ -1142,11 +1279,8 @@ void fib6_run_gc(unsigned long dummy)
}
gc_args.more = 0;


write_lock_bh(&rt6_lock);
ndisc_dst_gc(&gc_args.more);
fib6_clean_tree(&ip6_routing_table, fib6_age, 0, NULL);
write_unlock_bh(&rt6_lock);
fib6_clean_all(fib6_age, 0, NULL);

if (gc_args.more)
mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval);
Expand All @@ -1165,6 +1299,8 @@ void __init fib6_init(void)
NULL, NULL);
if (!fib6_node_kmem)
panic("cannot create fib6_nodes cache");

fib6_tables_init();
}

void fib6_gc_cleanup(void)
Expand Down
Loading

0 comments on commit c71099a

Please sign in to comment.