Skip to contentSkip to conversation

: Increase number of possible routing tables

RFC In review Patrick McHardy 5 participants 20 messages Jul 3, 2006 – Jul 8, 2006

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover : Increase number of possible routing tables

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

The table IDs are changed to 32 bit values and are contained in a new netlink routing attribute. For compatibility rtm_table in struct rtmsg can still be used to access the first 255 tables and contains the low 8 bit of the table ID in case of dumps. Unfortunately there are no invalid values for rtm_table, so the best userspace can do in case of a new iproute version that tries to access tables > 255 on an old kernel is to use RTM_UNSPEC (0) for rtm_table, which will make the kernel allocate an empty table instead of silently adding routes to a more or less random table. The iproute patch will follow shortly.

The hash tables are statically sized since on-the-fly resizing would require introducing locking in the packet processing path (currently we need none), if this is a problem we could just directly attach table references to rules, since tables are never deleted or freed this would be a simple change.

One spot is still missing (nl_fib_lookup), so these patches are purely a RFC for now. Tested only with IPv4, I mainly converted DECNET as well to keep it in sync and because iteration over all possible table values, as done in many spots, has an unacceptable overhead with 32 bit values.

 include/linux/rtnetlink.h |   11 +++
 include/net/dn_fib.h      |    7 +-
 include/net/ip_fib.h      |   39 ++++---------
 net/decnet/dn_fib.c       |   62 ++-------------------
 net/decnet/dn_route.c     |    1 
 net/decnet/dn_rules.c     |   12 ++--
 net/decnet/dn_table.c     |  133 ++++++++++++++++++++++++++++++++--------------
 net/ipv4/fib_frontend.c   |  115 +++++++++++++++++++++++++--------------
 net/ipv4/fib_hash.c       |   30 +++++-----
 net/ipv4/fib_lookup.h     |    4 -
 net/ipv4/fib_rules.c      |   18 +++---
 net/ipv4/fib_semantics.c  |    5 +
 net/ipv4/fib_trie.c       |   32 +++++------
 net/ipv4/route.c          |    1 
 net/ipv6/route.c          |    1 
 15 files changed, 255 insertions(+), 216 deletions(-)

Patrick McHardy:
[NET]: Use u32 for routing table IDs
[NET]: Introduce RTA_TABLE routing attribute [IPV4]: Increase number of possible routing tables to 2^32 [DECNET]: Increase number of possible routing tables to 2^32

#1 lore raw

RFC 1/4 : Use u32 for routing table IDs

[NET]: Use u32 for routing table IDs

Use u32 for routing table IDs in net/ipv4 and net/decnet in preparation of support for a larger number of routing tables. No functional changes are made by this patch.

---
commit 7e3ac412e095b5a4d29a7244d5cee795267a7c6a
tree cfcec90b10614b7a1401459f2ea0abec4e189799
parent f82bc1762e0e74b7e0040a4d83be06d32c37fc2e
author Patrick McHardy <[email protected]> Mon, 03 Jul 2006 07:43:07 +0200 committer Patrick McHardy <[email protected]> Mon, 03 Jul 2006 07:43:07 +0200

 include/net/dn_fib.h     |    4 ++--
 include/net/ip_fib.h     |   14 +++++++-------
 net/decnet/dn_fib.c      |    6 +++---
 net/decnet/dn_rules.c    |    4 ++--
 net/decnet/dn_table.c    |   10 +++++-----
 net/ipv4/fib_frontend.c  |    8 ++++----
 net/ipv4/fib_hash.c      |    4 ++--
 net/ipv4/fib_lookup.h    |    4 ++--
 net/ipv4/fib_rules.c     |    8 ++++----
 net/ipv4/fib_semantics.c |    4 ++--
 net/ipv4/fib_trie.c      |    6 +++---
 11 files changed, 36 insertions(+), 36 deletions(-)
include/net/dn_fib.h +2 -2
index a15dcf0..9464f48 100644
@@ -94,7 +94,7 @@ #define DN_FIB_INFO(f) ((f)->fn_info)
 
 
 struct dn_fib_table {
-	int n;
+	u32 n;
 
 	int (*insert)(struct dn_fib_table *t, struct rtmsg *r, 
 			struct dn_kern_rta *rta, struct nlmsghdr *n, 
@@ -137,7 +137,7 @@ extern int dn_fib_sync_up(struct net_dev
 /*
  * dn_tables.c
  */
-extern struct dn_fib_table *dn_fib_get_table(int n, int creat);
+extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
 extern struct dn_fib_table *dn_fib_empty_table(void);
 extern void dn_fib_table_init(void);
 extern void dn_fib_table_cleanup(void);
include/net/ip_fib.h +7 -7
index a095d1d..ddc3ced 100644
@@ -149,7 +149,7 @@ #define FIB_RES_NETMASK(res)	        (0)
 #endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
 
 struct fib_table {
-	unsigned char	tb_id;
+	u32		tb_id;
 	unsigned	tb_stamp;
 	int		(*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
 	int		(*tb_insert)(struct fib_table *table, struct rtmsg *r,
@@ -172,14 +172,14 @@ #ifndef CONFIG_IP_MULTIPLE_TABLES
 extern struct fib_table *ip_fib_local_table;
 extern struct fib_table *ip_fib_main_table;
 
-static inline struct fib_table *fib_get_table(int id)
+static inline struct fib_table *fib_get_table(u32 id)
 {
 	if (id != RT_TABLE_LOCAL)
 		return ip_fib_main_table;
 	return ip_fib_local_table;
 }
 
-static inline struct fib_table *fib_new_table(int id)
+static inline struct fib_table *fib_new_table(u32 id)
 {
 	return fib_get_table(id);
 }
@@ -204,10 +204,10 @@ #define ip_fib_main_table (fib_tables[RT
 
 extern struct fib_table * fib_tables[RT_TABLE_MAX+1];
 extern int fib_lookup(const struct flowi *flp, struct fib_result *res);
-extern struct fib_table *__fib_new_table(int id);
+extern struct fib_table *__fib_new_table(u32 id);
 extern void fib_rule_put(struct fib_rule *r);
 
-static inline struct fib_table *fib_get_table(int id)
+static inline struct fib_table *fib_get_table(u32 id)
 {
 	if (id == 0)
 		id = RT_TABLE_MAIN;
@@ -215,7 +215,7 @@ static inline struct fib_table *fib_get_
 	return fib_tables[id];
 }
 
-static inline struct fib_table *fib_new_table(int id)
+static inline struct fib_table *fib_new_table(u32 id)
 {
 	if (id == 0)
 		id = RT_TABLE_MAIN;
@@ -248,7 +248,7 @@ extern int fib_convert_rtentry(int cmd, 
 extern u32  __fib_res_prefsrc(struct fib_result *res);
 
 /* Exported by fib_hash.c */
-extern struct fib_table *fib_hash_init(int id);
+extern struct fib_table *fib_hash_init(u32 id);
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 /* Exported by fib_rules.c */
net/decnet/dn_fib.c +3 -3
index 0375077..f4c1c1e 100644
@@ -534,8 +534,8 @@ int dn_fib_rtm_newroute(struct sk_buff *
 
 int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	int t;
-	int s_t;
+	u32 t;
+	u32 s_t;
 	struct dn_fib_table *tb;
 
 	if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
@@ -765,7 +765,7 @@ void dn_fib_flush(void)
 {
         int flushed = 0;
         struct dn_fib_table *tb;
-        int id;
+        u32 id;
 
         for(id = RT_TABLE_MAX; id > 0; id--) {
                 if ((tb = dn_fib_get_table(id, 0)) == NULL)
net/decnet/dn_rules.c +2 -2
index 06e785f..16ca66b 100644
@@ -43,7 +43,7 @@ struct dn_fib_rule
 	struct hlist_node	r_hlist;
 	atomic_t		r_clntref;
 	u32			r_preference;
-	unsigned char		r_table;
+	u32			r_table;
 	unsigned char		r_action;
 	unsigned char		r_dst_len;
 	unsigned char		r_src_len;
@@ -130,7 +130,7 @@ int dn_fib_rtm_newrule(struct sk_buff *s
 	struct rtmsg *rtm = NLMSG_DATA(nlh);
 	struct dn_fib_rule *r, *new_r, *last = NULL;
 	struct hlist_node *node = NULL;
-	unsigned char table_id;
+	u32 table_id;
 
 	if (rtm->rtm_src_len > 16 || rtm->rtm_dst_len > 16)
 		return -EINVAL;
net/decnet/dn_table.c +5 -5
index 37d9d0a..7de6a88 100644
@@ -268,7 +268,7 @@ static int dn_fib_nh_match(struct rtmsg 
 }
 
 static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-                        u8 tb_id, u8 type, u8 scope, void *dst, int dst_len,
+                        u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
                         struct dn_fib_info *fi, unsigned int flags)
 {
         struct rtmsg *rtm;
@@ -331,7 +331,7 @@ rtattr_failure:
 }
 
 
-static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id,
+static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
                         struct nlmsghdr *nlh, struct netlink_skb_parms *req)
 {
         struct sk_buff *skb;
@@ -744,7 +744,7 @@ out:
 }
 
 
-struct dn_fib_table *dn_fib_get_table(int n, int create)
+struct dn_fib_table *dn_fib_get_table(u32 n, int create)
 {
         struct dn_fib_table *t;
 
@@ -781,7 +781,7 @@ struct dn_fib_table *dn_fib_get_table(in
         return t;
 }
 
-static void dn_fib_del_tree(int n)
+static void dn_fib_del_tree(u32 n)
 {
 	struct dn_fib_table *t;
 
@@ -795,7 +795,7 @@ static void dn_fib_del_tree(int n)
 
 struct dn_fib_table *dn_fib_empty_table(void)
 {
-        int id;
+        u32 id;
 
         for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
                 if (dn_fib_tables[id] == NULL)
net/ipv4/fib_frontend.c +4 -4
index ba2a707..4d5429a 100644
@@ -61,7 +61,7 @@ #define RT_TABLE_MIN 1
 
 struct fib_table *fib_tables[RT_TABLE_MAX+1];
 
-struct fib_table *__fib_new_table(int id)
+struct fib_table *__fib_new_table(u32 id)
 {
 	struct fib_table *tb;
 
@@ -81,7 +81,7 @@ static void fib_flush(void)
 	int flushed = 0;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	struct fib_table *tb;
-	int id;
+	u32 id;
 
 	for (id = RT_TABLE_MAX; id>0; id--) {
 		if ((tb = fib_get_table(id))==NULL)
@@ -332,8 +332,8 @@ int inet_rtm_newroute(struct sk_buff *sk
 
 int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	int t;
-	int s_t;
+	u32 t;
+	u32 s_t;
 	struct fib_table *tb;
 
 	if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
net/ipv4/fib_hash.c +2 -2
index 3c1d32a..4b79173 100644
@@ -766,9 +766,9 @@ static int fn_hash_dump(struct fib_table
 }
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
-struct fib_table * fib_hash_init(int id)
+struct fib_table * fib_hash_init(u32 id)
 #else
-struct fib_table * __init fib_hash_init(int id)
+struct fib_table * __init fib_hash_init(u32 id)
 #endif
 {
 	struct fib_table *tb;
net/ipv4/fib_lookup.h +2 -2
index ef6609e..ddd5249 100644
@@ -30,11 +30,11 @@ extern struct fib_info *fib_create_info(
 extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *,
 			struct kern_rta *rta, struct fib_info *fi);
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			 u8 tb_id, u8 type, u8 scope, void *dst,
+			 u32 tb_id, u8 type, u8 scope, void *dst,
 			 int dst_len, u8 tos, struct fib_info *fi,
 			 unsigned int);
 extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
-		      int z, int tb_id,
+		      int z, u32 tb_id,
 		      struct nlmsghdr *n, struct netlink_skb_parms *req);
 extern struct fib_alias *fib_find_alias(struct list_head *fah,
 					u8 tos, u32 prio);
net/ipv4/fib_rules.c +4 -4
index 6c642d1..71ede02 100644
@@ -56,7 +56,7 @@ struct fib_rule
 	struct hlist_node hlist;
 	atomic_t	r_clntref;
 	u32		r_preference;
-	unsigned char	r_table;
+	u32		r_table;
 	unsigned char	r_action;
 	unsigned char	r_dst_len;
 	unsigned char	r_src_len;
@@ -145,7 +145,7 @@ #endif
 
 static struct fib_table *fib_empty_table(void)
 {
-	int id;
+	u32 id;
 
 	for (id = 1; id <= RT_TABLE_MAX; id++)
 		if (fib_tables[id] == NULL)
@@ -177,7 +177,7 @@ int inet_rtm_newrule(struct sk_buff *skb
 	struct rtmsg *rtm = NLMSG_DATA(nlh);
 	struct fib_rule *r, *new_r, *last = NULL;
 	struct hlist_node *node = NULL;
-	unsigned char table_id;
+	u32 table_id;
 
 	if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 ||
 	    (rtm->rtm_tos & ~IPTOS_TOS_MASK))
@@ -320,7 +320,7 @@ #endif
 		    (r->r_ifindex && r->r_ifindex != flp->iif))
 			continue;
 
-FRprintk("tb %d r %d ", r->r_table, r->r_action);
+FRprintk("tb %u r %d ", r->r_table, r->r_action);
 		switch (r->r_action) {
 		case RTN_UNICAST:
 			policy = r;
net/ipv4/fib_semantics.c +2 -2
index 5f87533..84537df 100644
@@ -273,7 +273,7 @@ int ip_fib_check_default(u32 gw, struct 
 }
 
 void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
-	       int z, int tb_id,
+	       int z, u32 tb_id,
 	       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct sk_buff *skb;
@@ -940,7 +940,7 @@ u32 __fib_res_prefsrc(struct fib_result 
 
 int
 fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-	      u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
+	      u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
 	      struct fib_info *fi, unsigned int flags)
 {
 	struct rtmsg *rtm;
net/ipv4/fib_trie.c +3 -3
index 1cb6530..3936f16 100644
@@ -1148,7 +1148,7 @@ fn_trie_insert(struct fib_table *tb, str
 
 	key = ntohl(key);
 
-	pr_debug("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
+	pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen);
 
 	mask = ntohl(inet_make_mask(plen));
 
@@ -1943,9 +1943,9 @@ out:
 /* Fix more generic FIB names for init later */
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
-struct fib_table * fib_hash_init(int id)
+struct fib_table * fib_hash_init(u32 id)
 #else
-struct fib_table * __init fib_hash_init(int id)
+struct fib_table * __init fib_hash_init(u32 id)
 #endif
 {
 	struct fib_table *tb;
#2 lore raw

RFC 2/4 : Introduce RTA_TABLE routing attribute

In reply to Patrick McHardy

[NET]: Introduce RTA_TABLE routing attribute

Introduce RTA_TABLE routing attribute to hold 32 bit routing table IDs. Usespace compatibility is provided by continuing to accept and send the rtm_table field, but because of its limited size it can only carry the low 8 bits of the table ID. This implies that if larger IDs are used, _all_ userspace programs using them need to use RTA_TABLE.

---
commit 8cf1ae7345f935350dede855381dfbb620cabc1c
tree d674b6bb251dda0fcb915db0dbca98cda7779348
parent 7e3ac412e095b5a4d29a7244d5cee795267a7c6a
author Patrick McHardy <[email protected]> Mon, 03 Jul 2006 08:13:14 +0200 committer Patrick McHardy <[email protected]> Mon, 03 Jul 2006 08:13:14 +0200

 include/linux/rtnetlink.h |    8 ++++++++
 net/decnet/dn_fib.c       |    7 ++++---
 net/decnet/dn_route.c     |    1 +
 net/decnet/dn_rules.c     |    6 ++++--
 net/decnet/dn_table.c     |    1 +
 net/ipv4/fib_frontend.c   |    7 ++++---
 net/ipv4/fib_rules.c      |    6 ++++--
 net/ipv4/fib_semantics.c  |    1 +
 net/ipv4/route.c          |    1 +
 net/ipv6/route.c          |    1 +
 10 files changed, 29 insertions(+), 10 deletions(-)
include/linux/rtnetlink.h +8 -0
index facd9ee..8f6efff 100644
@@ -263,6 +263,7 @@ enum rtattr_type_t
 	RTA_CACHEINFO,
 	RTA_SESSION,
 	RTA_MP_ALGO,
+	RTA_TABLE,
 	__RTA_MAX
 };
 
@@ -1065,6 +1066,13 @@ #define BUG_TRAP(x) do { \
 	} \
 } while(0)
 
+static inline u32 rtm_get_table(struct rtmsg *rtm, struct rtattr **rta)
+{
+	return RTA_GET_U32(rta[RTA_TABLE-1]);
+rtattr_failure:
+	return rtm->rtm_table;
+}
+
 #endif /* __KERNEL__ */
 
 
net/decnet/dn_fib.c +4 -3
index f4c1c1e..a43e59b 100644
@@ -491,7 +491,8 @@ static int dn_fib_check_attr(struct rtms
 		if (attr) {
 			if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
 				return -EINVAL;
-			if (i != RTA_MULTIPATH && i != RTA_METRICS)
+			if (i != RTA_MULTIPATH && i != RTA_METRICS &&
+			    i != RTA_TABLE)
 				rta[i-1] = (struct rtattr *)RTA_DATA(attr);
 		}
 	}
@@ -508,7 +509,7 @@ int dn_fib_rtm_delroute(struct sk_buff *
 	if (dn_fib_check_attr(r, rta))
 		return -EINVAL;
 
-	tb = dn_fib_get_table(r->rtm_table, 0);
+	tb = dn_fib_get_table(rtm_get_table(r, rta), 0);
 	if (tb)
 		return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
 
@@ -524,7 +525,7 @@ int dn_fib_rtm_newroute(struct sk_buff *
 	if (dn_fib_check_attr(r, rta))
 		return -EINVAL;
 
-	tb = dn_fib_get_table(r->rtm_table, 1);
+	tb = dn_fib_get_table(rtm_get_table(r, rta), 1);
 	if (tb) 
 		return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
 
net/decnet/dn_route.c +1 -0
index 1355614..2c5bc4e 100644
@@ -1480,6 +1480,7 @@ static int dn_rt_fill_info(struct sk_buf
 	r->rtm_src_len = 0;
 	r->rtm_tos = 0;
 	r->rtm_table = RT_TABLE_MAIN;
+	RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
 	r->rtm_type = rt->rt_type;
 	r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
 	r->rtm_scope = RT_SCOPE_UNIVERSE;
net/decnet/dn_rules.c +4 -2
index 16ca66b..d274d59 100644
@@ -77,6 +77,7 @@ int dn_fib_rtm_delrule(struct sk_buff *s
 	struct rtmsg *rtm = NLMSG_DATA(nlh);
 	struct dn_fib_rule *r;
 	struct hlist_node *node;
+	u32 table = rtm_get_table(rtm, rta);
 	int err = -ESRCH;
 
 	hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) {
@@ -90,7 +91,7 @@ #endif
 			(!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
 			(!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
 			(!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) &&
-			(!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
+			(!table || (r && table == r->r_table))) {
 
 			err = -EPERM;
 			if (r == &default_rule)
@@ -141,7 +142,7 @@ int dn_fib_rtm_newrule(struct sk_buff *s
 	if (rtm->rtm_type == RTN_NAT)
 		return -EINVAL;
 
-	table_id = rtm->rtm_table;
+	table_id = rtm_get_table(rtm, rta);
 	if (table_id == RT_TABLE_UNSPEC) {
 		struct dn_fib_table *tb;
 		if (rtm->rtm_type == RTN_UNICAST) {
@@ -365,6 +366,7 @@ #ifdef CONFIG_DECNET_ROUTE_FWMARK
 		RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark);
 #endif
 	rtm->rtm_table = r->r_table;
+	RTA_PUT_U32(skb, RTA_TABLE, r->r_table);
 	rtm->rtm_protocol = 0;
 	rtm->rtm_scope = 0;
 	rtm->rtm_type = r->r_action;
net/decnet/dn_table.c +1 -0
index 7de6a88..b165282 100644
@@ -282,6 +282,7 @@ static int dn_fib_dump_info(struct sk_bu
         rtm->rtm_src_len = 0;
         rtm->rtm_tos = 0;
         rtm->rtm_table = tb_id;
+	RTA_PUT_U32(skb, RTA_TABLE, tb_id);
         rtm->rtm_flags = fi->fib_flags;
         rtm->rtm_scope = scope;
 	rtm->rtm_type  = type;
net/ipv4/fib_frontend.c +4 -3
index 4d5429a..2f54f22 100644
@@ -293,7 +293,8 @@ static int inet_check_attr(struct rtmsg 
 		if (attr) {
 			if (RTA_PAYLOAD(attr) < 4)
 				return -EINVAL;
-			if (i != RTA_MULTIPATH && i != RTA_METRICS)
+			if (i != RTA_MULTIPATH && i != RTA_METRICS &&
+			    i != RTA_TABLE)
 				*rta = (struct rtattr*)RTA_DATA(attr);
 		}
 	}
@@ -309,7 +310,7 @@ int inet_rtm_delroute(struct sk_buff *sk
 	if (inet_check_attr(r, rta))
 		return -EINVAL;
 
-	tb = fib_get_table(r->rtm_table);
+	tb = fib_get_table(rtm_get_table(r, rta));
 	if (tb)
 		return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
 	return -ESRCH;
@@ -324,7 +325,7 @@ int inet_rtm_newroute(struct sk_buff *sk
 	if (inet_check_attr(r, rta))
 		return -EINVAL;
 
-	tb = fib_new_table(r->rtm_table);
+	tb = fib_new_table(rtm_get_table(r, rta));
 	if (tb)
 		return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
 	return -ENOBUFS;
net/ipv4/fib_rules.c +4 -2
index 71ede02..e6d1f5a 100644
@@ -111,6 +111,7 @@ int inet_rtm_delrule(struct sk_buff *skb
 	struct rtmsg *rtm = NLMSG_DATA(nlh);
 	struct fib_rule *r;
 	struct hlist_node *node;
+	u32 table = rtm_get_table(rtm, rta);
 	int err = -ESRCH;
 
 	hlist_for_each_entry(r, node, &fib_rules, hlist) {
@@ -125,7 +126,7 @@ #endif
 		    (!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
 		    (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
 		    (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) &&
-		    (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
+		    (!table || (r && table == r->r_table))) {
 			err = -EPERM;
 			if (r == &local_rule)
 				break;
@@ -186,7 +187,7 @@ int inet_rtm_newrule(struct sk_buff *skb
 	if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ)
 		return -EINVAL;
 
-	table_id = rtm->rtm_table;
+	table_id = rtm_get_table(rtm, rta);
 	if (table_id == RT_TABLE_UNSPEC) {
 		struct fib_table *table;
 		if (rtm->rtm_type == RTN_UNICAST) {
@@ -403,6 +404,7 @@ #ifdef CONFIG_IP_ROUTE_FWMARK
 		RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark);
 #endif
 	rtm->rtm_table = r->r_table;
+	RTA_PUT_U32(skb, RTA_TABLE, r->r_table);
 	rtm->rtm_protocol = 0;
 	rtm->rtm_scope = 0;
 	rtm->rtm_type = r->r_action;
net/ipv4/fib_semantics.c +1 -0
index 84537df..3c45256 100644
@@ -954,6 +954,7 @@ fib_dump_info(struct sk_buff *skb, u32 p
 	rtm->rtm_src_len = 0;
 	rtm->rtm_tos = tos;
 	rtm->rtm_table = tb_id;
+	RTA_PUT_U32(skb, RTA_TABLE, tb_id);
 	rtm->rtm_type = type;
 	rtm->rtm_flags = fi->fib_flags;
 	rtm->rtm_scope = scope;
net/ipv4/route.c +1 -0
index da44fab..7ef78f3 100644
@@ -2638,6 +2638,7 @@ #endif
 	r->rtm_src_len	= 0;
 	r->rtm_tos	= rt->fl.fl4_tos;
 	r->rtm_table	= RT_TABLE_MAIN;
+	RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
 	r->rtm_type	= rt->rt_type;
 	r->rtm_scope	= RT_SCOPE_UNIVERSE;
 	r->rtm_protocol = RTPROT_UNSPEC;
net/ipv6/route.c +1 -0
index 87c39c9..4410282 100644
@@ -1745,6 +1745,7 @@ static int rt6_fill_node(struct sk_buff 
 	rtm->rtm_src_len = rt->rt6i_src.plen;
 	rtm->rtm_tos = 0;
 	rtm->rtm_table = RT_TABLE_MAIN;
+	RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
 	if (rt->rt6i_flags&RTF_REJECT)
 		rtm->rtm_type = RTN_UNREACHABLE;
 	else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
#3 lore raw

RFC 3/4 : Increase number of possible routing tables to 2^32

In reply to Patrick McHardy

[IPV4]: Increase number of possible routing tables to 2^32

Increase the nubmer of possible routing tables to 2^32 by replacing the fixed sized array of tables by a hash table.

---
commit aab791510bc6fb2392ac361b0375f60a24b02659
tree f198102cd18b1a6233c573cf4f1f5f0b8827e724
parent 8cf1ae7345f935350dede855381dfbb620cabc1c
author Patrick McHardy <[email protected]> Mon, 03 Jul 2006 09:21:22 +0200 committer Patrick McHardy <[email protected]> Mon, 03 Jul 2006 09:21:22 +0200

 include/linux/rtnetlink.h |    3 -
 include/net/ip_fib.h      |   25 ++---------
 net/ipv4/fib_frontend.c   |  100 ++++++++++++++++++++++++++++++---------------
 net/ipv4/fib_hash.c       |   26 ++++++------
 net/ipv4/fib_rules.c      |    4 +-
 net/ipv4/fib_trie.c       |   26 ++++++------
 6 files changed, 100 insertions(+), 84 deletions(-)
include/linux/rtnetlink.h +1 -2
index 8f6efff..c1217e4 100644
@@ -238,9 +238,8 @@ enum rt_class_t
 	RT_TABLE_DEFAULT=253,
 	RT_TABLE_MAIN=254,
 	RT_TABLE_LOCAL=255,
-	__RT_TABLE_MAX
 };
-#define RT_TABLE_MAX (__RT_TABLE_MAX - 1)
+#define RT_TABLE_MAX 0xFFFFFFFF
 
 
 
include/net/ip_fib.h +5 -20
index ddc3ced..4b764e2 100644
@@ -149,6 +149,7 @@ #define FIB_RES_NETMASK(res)	        (0)
 #endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
 
 struct fib_table {
+	struct hlist_node tb_hlist;
 	u32		tb_id;
 	unsigned	tb_stamp;
 	int		(*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
@@ -199,30 +200,14 @@ static inline void fib_select_default(co
 }
 
 #else /* CONFIG_IP_MULTIPLE_TABLES */
-#define ip_fib_local_table (fib_tables[RT_TABLE_LOCAL])
-#define ip_fib_main_table (fib_tables[RT_TABLE_MAIN])
+#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL)
+#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN)
 
-extern struct fib_table * fib_tables[RT_TABLE_MAX+1];
 extern int fib_lookup(const struct flowi *flp, struct fib_result *res);
-extern struct fib_table *__fib_new_table(u32 id);
+extern struct fib_table *fib_new_table(u32 id);
+extern struct fib_table *fib_get_table(u32 id);
 extern void fib_rule_put(struct fib_rule *r);
 
-static inline struct fib_table *fib_get_table(u32 id)
-{
-	if (id == 0)
-		id = RT_TABLE_MAIN;
-
-	return fib_tables[id];
-}
-
-static inline struct fib_table *fib_new_table(u32 id)
-{
-	if (id == 0)
-		id = RT_TABLE_MAIN;
-
-	return fib_tables[id] ? : __fib_new_table(id);
-}
-
 extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
 
 #endif /* CONFIG_IP_MULTIPLE_TABLES */
net/ipv4/fib_frontend.c +66 -34

158 lines not on this page · raw message

net/ipv4/fib_hash.c +13 -13
index 4b79173..fcbf2d6 100644
@@ -685,7 +685,7 @@ fn_hash_dump_bucket(struct sk_buff *skb,
 	struct fib_node *f;
 	int i, s_i;
 
-	s_i = cb->args[3];
+	s_i = cb->args[4];
 	i = 0;
 	hlist_for_each_entry(f, node, head, fn_hash) {
 		struct fib_alias *fa;
@@ -705,14 +705,14 @@ fn_hash_dump_bucket(struct sk_buff *skb,
 					  fa->fa_tos,
 					  fa->fa_info,
 					  NLM_F_MULTI) < 0) {
-				cb->args[3] = i;
+				cb->args[4] = i;
 				return -1;
 			}
 		next:
 			i++;
 		}
 	}
-	cb->args[3] = i;
+	cb->args[4] = i;
 	return skb->len;
 }
 
@@ -723,21 +723,21 @@ fn_hash_dump_zone(struct sk_buff *skb, s
 {
 	int h, s_h;
 
-	s_h = cb->args[2];
+	s_h = cb->args[3];
 	for (h=0; h < fz->fz_divisor; h++) {
 		if (h < s_h) continue;
 		if (h > s_h)
-			memset(&cb->args[3], 0,
-			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
+			memset(&cb->args[4], 0,
+			       sizeof(cb->args) - 4*sizeof(cb->args[0]));
 		if (fz->fz_hash == NULL ||
 		    hlist_empty(&fz->fz_hash[h]))
 			continue;
 		if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) {
-			cb->args[2] = h;
+			cb->args[3] = h;
 			return -1;
 		}
 	}
-	cb->args[2] = h;
+	cb->args[3] = h;
 	return skb->len;
 }
 
@@ -747,21 +747,21 @@ static int fn_hash_dump(struct fib_table
 	struct fn_zone *fz;
 	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
 
-	s_m = cb->args[1];
+	s_m = cb->args[2];
 	read_lock(&fib_hash_lock);
 	for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
 		if (m < s_m) continue;
 		if (m > s_m)
-			memset(&cb->args[2], 0,
-			       sizeof(cb->args) - 2*sizeof(cb->args[0]));
+			memset(&cb->args[3], 0,
+			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
 		if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
-			cb->args[1] = m;
+			cb->args[2] = m;
 			read_unlock(&fib_hash_lock);
 			return -1;
 		}
 	}
 	read_unlock(&fib_hash_lock);
-	cb->args[1] = m;
+	cb->args[2] = m;
 	return skb->len;
 }
 
net/ipv4/fib_rules.c +2 -2
index e6d1f5a..a41ab4b 100644
@@ -149,8 +149,8 @@ static struct fib_table *fib_empty_table
 	u32 id;
 
 	for (id = 1; id <= RT_TABLE_MAX; id++)
-		if (fib_tables[id] == NULL)
-			return __fib_new_table(id);
+		if (fib_get_table(id) == NULL)
+			return fib_new_table(id);
 	return NULL;
 }
 
net/ipv4/fib_trie.c +13 -13
index 3936f16..92b1d77 100644
@@ -1848,7 +1848,7 @@ static int fn_trie_dump_fa(t_key key, in
 
 	u32 xkey = htonl(key);
 
-	s_i = cb->args[3];
+	s_i = cb->args[4];
 	i = 0;
 
 	/* rcu_read_lock is hold by caller */
@@ -1870,12 +1870,12 @@ static int fn_trie_dump_fa(t_key key, in
 				  plen,
 				  fa->fa_tos,
 				  fa->fa_info, 0) < 0) {
-			cb->args[3] = i;
+			cb->args[4] = i;
 			return -1;
 		}
 		i++;
 	}
-	cb->args[3] = i;
+	cb->args[4] = i;
 	return skb->len;
 }
 
@@ -1886,14 +1886,14 @@ static int fn_trie_dump_plen(struct trie
 	struct list_head *fa_head;
 	struct leaf *l = NULL;
 
-	s_h = cb->args[2];
+	s_h = cb->args[3];
 
 	for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
 		if (h < s_h)
 			continue;
 		if (h > s_h)
-			memset(&cb->args[3], 0,
-			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
+			memset(&cb->args[4], 0,
+			       sizeof(cb->args) - 4*sizeof(cb->args[0]));
 
 		fa_head = get_fa_head(l, plen);
 
@@ -1904,11 +1904,11 @@ static int fn_trie_dump_plen(struct trie
 			continue;
 
 		if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
-			cb->args[2] = h;
+			cb->args[3] = h;
 			return -1;
 		}
 	}
-	cb->args[2] = h;
+	cb->args[3] = h;
 	return skb->len;
 }
 
@@ -1917,23 +1917,23 @@ static int fn_trie_dump(struct fib_table
 	int m, s_m;
 	struct trie *t = (struct trie *) tb->tb_data;
 
-	s_m = cb->args[1];
+	s_m = cb->args[2];
 
 	rcu_read_lock();
 	for (m = 0; m <= 32; m++) {
 		if (m < s_m)
 			continue;
 		if (m > s_m)
-			memset(&cb->args[2], 0,
-				sizeof(cb->args) - 2*sizeof(cb->args[0]));
+			memset(&cb->args[3], 0,
+				sizeof(cb->args) - 3*sizeof(cb->args[0]));
 
 		if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
-			cb->args[1] = m;
+			cb->args[2] = m;
 			goto out;
 		}
 	}
 	rcu_read_unlock();
-	cb->args[1] = m;
+	cb->args[2] = m;
 	return skb->len;
 out:
 	rcu_read_unlock();
#4 lore raw

RFC 4/4 : Increase number of possible routing tables to 2^32

In reply to Patrick McHardy

[DECNET]: Increase number of possible routing tables to 2^32

Increase the nubmer of possible routing tables to 2^32 by replacing the fixed sized array of tables by a hash table.

---
commit 2bafd208cbec6b6291662bf39d94f1f9e3a54e31
tree 1b922ca700a00f4fcb97d7567d85bd9d49b5bc90
parent aab791510bc6fb2392ac361b0375f60a24b02659
author Patrick McHardy <[email protected]> Mon, 03 Jul 2006 09:21:50 +0200 committer Patrick McHardy <[email protected]> Mon, 03 Jul 2006 09:21:50 +0200

 include/net/dn_fib.h  |    3 -
 net/decnet/dn_fib.c   |   49 --------------------
 net/decnet/dn_rules.c |    2 -
 net/decnet/dn_table.c |  122 +++++++++++++++++++++++++++++++++++--------------
 4 files changed, 90 insertions(+), 86 deletions(-)
include/net/dn_fib.h +1 -2
index 9464f48..8098bdd 100644
@@ -94,6 +94,7 @@ #define DN_FIB_INFO(f) ((f)->fn_info)
 
 
 struct dn_fib_table {
+	struct hlist_node hlist;
 	u32 n;
 
 	int (*insert)(struct dn_fib_table *t, struct rtmsg *r, 
@@ -179,8 +180,6 @@ static inline void dn_fib_res_put(struct
 		dn_fib_rule_put(res->r);
 }
 
-extern struct dn_fib_table *dn_fib_tables[];
-
 #else /* Endnode */
 
 #define dn_fib_init()  do { } while(0)
net/decnet/dn_fib.c +0 -49

61 lines not on this page · raw message

net/decnet/dn_rules.c +1 -1
index d274d59..6d1752a 100644
@@ -273,7 +273,7 @@ unsigned dnet_addr_type(__le16 addr)
 	struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } };
 	struct dn_fib_res res;
 	unsigned ret = RTN_UNICAST;
-	struct dn_fib_table *tb = dn_fib_tables[RT_TABLE_LOCAL];
+	struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
 
 	res.r = NULL;
 
net/decnet/dn_table.c +88 -34

218 lines not on this page · raw message

#5 lore raw

Re: [RFC DECNET 04/04]: Increase number of possible routing tables to 2^32

Hi,

Quoted 7 lines · Patrick McHardy

[DECNET]: Increase number of possible routing tables to 2^32

Increase the nubmer of possible routing tables to 2^32 by replacing the fixed sized array of tables by a hash table.

I've had a quick look though the DECnet parts of this and it looks good, atthough I've not had a chance to test it at all. Please cc Patrick Caulfield on DECnet changes,

Steve.

#6 lore raw

Re: [RFC DECNET 04/04]: Increase number of possible routing tables to 2^32

Quoted 6 lines · Steven Whitehouse

Hi,

Quoted 2 lines · Patrick McHardy

[DECNET]: Increase number of possible routing tables to 2^32

Quoted 8 lines
Quoted 5 lines

Increase the nubmer of possible routing tables to 2^32 by replacing the fixed sized array of tables by a hash table.

I've had a quick look though the DECnet parts of this and it looks good, atthough I've not had a chance to test it at all. Please cc Patrick Caulfield on DECnet changes,

Thanks, will do on the next submission.

#7 lore raw
In reply to Patrick McHardy
Quoted 11 lines · Patrick McHardy

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

The table IDs are changed to 32 bit values and are contained in a new netlink routing attribute. For compatibility rtm_table in struct rtmsg can still be used to access the first 255 tables and contains the low 8 bit of the table ID in case of dumps. Unfortunately there are no invalid values for rtm_table, so the best userspace can do in case of a new iproute version that tries to access tables > 255 on an old kernel is to use RTM_UNSPEC (0) for rtm_table, which will make the kernel allocate an empty table instead of silently adding routes to a more or less random table. The iproute patch will follow shortly.

Actually that last part wasn't entirely true. The last couple of releases of the kernel include the inet_check_attr function, which (unwillingly) breaks with the tradition of ignoring unknown attributes and signals an error on receiving the RTA_TABLE attribute. So the iproute patch only includes the RTA_TABLE attribute when the table ID is > 255, in which case rtm_table is set to RT_TABLE_UNSPEC. Old kernels will still have the behaviour I described above. The patch has been tested to behave as expected on both patched and unpatched kernels.

include/linux/rtnetlink.h +2 -2
index 5e33a20..7573c62 100644
@@ -238,9 +238,8 @@ enum rt_class_t
 	RT_TABLE_DEFAULT=253,
 	RT_TABLE_MAIN=254,
 	RT_TABLE_LOCAL=255,
-	__RT_TABLE_MAX
 };
-#define RT_TABLE_MAX (__RT_TABLE_MAX - 1)
+#define RT_TABLE_MAX 0xFFFFFFFF
 
 
 
@@ -263,6 +262,7 @@ enum rtattr_type_t
 	RTA_CACHEINFO,
 	RTA_SESSION,
 	RTA_MP_ALGO,
+	RTA_TABLE,
 	__RTA_MAX
 };
 
include/rt_names.h +1 -1
index 2d9ef10..07a10e0 100644
@@ -5,7 +5,7 @@ #include <asm/types.h>
 
 char* rtnl_rtprot_n2a(int id, char *buf, int len);
 char* rtnl_rtscope_n2a(int id, char *buf, int len);
-char* rtnl_rttable_n2a(int id, char *buf, int len);
+char* rtnl_rttable_n2a(__u32 id, char *buf, int len);
 char* rtnl_rtrealm_n2a(int id, char *buf, int len);
 char* rtnl_dsfield_n2a(int id, char *buf, int len);
 int rtnl_rtprot_a2n(__u32 *id, char *arg);
ip/ip_common.h +8 -0
index 1fe4a69..8b286b0 100644
@@ -32,4 +32,12 @@ extern int do_multiaddr(int argc, char *
 extern int do_multiroute(int argc, char **argv);
 extern int do_xfrm(int argc, char **argv);
 
+static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb)
+{
+	__u32 table = r->rtm_table;
+	if (tb[RTA_TABLE])
+		table = *(__u32*) RTA_DATA(tb[RTA_TABLE]);
+	return table;
+}
+
 extern struct rtnl_handle rth;
ip/iproute.c +28 -21

96 lines not on this page · raw message

ip/iprule.c +11 -3
index ccf699f..6caf573 100644
@@ -27,6 +27,7 @@ #include <string.h>
 
 #include "rt_names.h"
 #include "utils.h"
+#include "ip_common.h"
 
 extern struct rtnl_handle rth;
 
@@ -51,6 +52,7 @@ static int print_rule(const struct socka
 	struct rtmsg *r = NLMSG_DATA(n);
 	int len = n->nlmsg_len;
 	int host_len = -1;
+	__u32 table;
 	struct rtattr * tb[RTA_MAX+1];
 	char abuf[256];
 	SPRINT_BUF(b1);
@@ -129,8 +131,9 @@ static int print_rule(const struct socka
 		fprintf(fp, "iif %s ", (char*)RTA_DATA(tb[RTA_IIF]));
 	}
 
-	if (r->rtm_table)
-		fprintf(fp, "lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1, sizeof(b1)));
+	table = rtm_get_table(r, tb);
+	if (table)
+		fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
 
 	if (tb[RTA_FLOW]) {
 		__u32 to = *(__u32*)RTA_DATA(tb[RTA_FLOW]);
@@ -257,7 +260,12 @@ static int iprule_modify(int cmd, int ar
 			NEXT_ARG();
 			if (rtnl_rttable_a2n(&tid, *argv))
 				invarg("invalid table ID\n", *argv);
-			req.r.rtm_table = tid;
+			if (tid < 256)
+				req.r.rtm_table = tid;
+			else {
+				req.r.rtm_table = RT_TABLE_UNSPEC;
+				addattr32(&req.n, sizeof(req), RTA_TABLE, tid);
+			}
 			table_ok = 1;
 		} else if (strcmp(*argv, "dev") == 0 ||
 			   strcmp(*argv, "iif") == 0) {
lib/rt_names.c +75 -23

147 lines not on this page · raw message

#8 lore raw
Quoted 15 lines · Patrick McHardy
Quoted 11 lines · Patrick McHardy

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

The table IDs are changed to 32 bit values and are contained in a new netlink routing attribute. For compatibility rtm_table in struct rtmsg can still be used to access the first 255 tables and contains the low 8 bit of the table ID in case of dumps. Unfortunately there are no invalid values for rtm_table, so the best userspace can do in case of a new iproute version that tries to access tables > 255 on an old kernel is to use RTM_UNSPEC (0) for rtm_table, which will make the kernel allocate an empty table instead of silently adding routes to a more or less random table. The iproute patch will follow shortly.

Quoted 9 lines

Actually that last part wasn't entirely true. The last couple of releases of the kernel include the inet_check_attr function, which (unwillingly) breaks with the tradition of ignoring unknown attributes and signals an error on receiving the RTA_TABLE attribute. So the iproute patch only includes the RTA_TABLE attribute when the table ID is > 255, in which case rtm_table is set to RT_TABLE_UNSPEC. Old kernels will still have the behaviour I described above. The patch has been tested to behave as expected on both patched and unpatched kernels.

That wasn't entirely true either, its not inet_check_attr but rtnetlink_rcv_message that aborts, and it does this on all kernels. Somehow I thought unknown attributes were usually ignored .. anyway, this is a good thing in this case as it will avoid unexpected behaviour and simply return an error on kernels where this feature is not available.

#9 lore raw

* Patrick McHardy <[email protected]> 2006-07-03 11:38

Quoted 4 lines

That wasn't entirely true either, its not inet_check_attr but rtnetlink_rcv_message that aborts, and it does this on all kernels. Somehow I thought unknown attributes were usually ignored ..

This only applies to the first level of rtnetlink attributes, when using rtattr_parse() unknown attributes are ignored.

Once this ugly rta_buf has disappeared it will become more consistent.

Patches look good to me except that new iproute binaries won't work with older kernels anymore?

#10 lore raw
Quoted 8 lines · Thomas Graf

* Patrick McHardy <[email protected]> 2006-07-03 11:38

Quoted 4 lines

That wasn't entirely true either, its not inet_check_attr but rtnetlink_rcv_message that aborts, and it does this on all kernels. Somehow I thought unknown attributes were usually ignored ..

Quoted 8 lines

This only applies to the first level of rtnetlink attributes, when using rtattr_parse() unknown attributes are ignored.

Once this ugly rta_buf has disappeared it will become more consistent.

Patches look good to me except that new iproute binaries won't work with older kernels anymore?

They will as long as this feature isn't used, the RTA_TABLE attribute is only added to the message when the table id is > 255. Worked fine during my tests, or are you refering to something else?

#11 lore raw

* Patrick McHardy <[email protected]> 2006-07-03 13:36

Quoted 4 lines

They will as long as this feature isn't used, the RTA_TABLE attribute is only added to the message when the table id is > 255. Worked fine during my tests, or are you refering to something else?

Perfect, I said nothing :)

#12 lore raw
In reply to Patrick McHardy
Quoted 17 lines · Patrick McHardy

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

The table IDs are changed to 32 bit values and are contained in a new netlink routing attribute. For compatibility rtm_table in struct rtmsg can still be used to access the first 255 tables and contains the low 8 bit of the table ID in case of dumps. Unfortunately there are no invalid values for rtm_table, so the best userspace can do in case of a new iproute version that tries to access tables > 255 on an old kernel is to use RTM_UNSPEC (0) for rtm_table, which will make the kernel allocate an empty table instead of silently adding routes to a more or less random table. The iproute patch will follow shortly.

The hash tables are statically sized since on-the-fly resizing would require introducing locking in the packet processing path (currently we need none), if this is a problem we could just directly attach table references to rules, since tables are never deleted or freed this would be a simple change.

Quoted 4 lines

One spot is still missing (nl_fib_lookup), so these patches are purely a RFC for now. Tested only with IPv4, I mainly converted DECNET as well to keep it in sync and because iteration over all possible table values, as done in many spots, has an unacceptable overhead with 32 bit values.

Since there were no objections, I would like to finalize this patch by takeing care of nl_fib_lookup. Since it was introduced as a debugging interface for fib_trie and the interface definitions are not even public (contained in include/net), I wonder if anyone really cares about backwards compatibility or if I can just change it.

Robert, Thomas, you are the only two users of the interface I'm aware of, what do you think?

#13 lore raw
Quoted 4 lines · Patrick McHardy
Quoted 2 lines · Patrick McHardy

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

I am seeing problems..though they could be with the way I'm using the tool or pehaps I patched the kernel incorrectly.

I applied the 3 patches to 2.6.17..all patches applied without problem, but with a few lines of fuzz. I get the same behaviour with and without the new 'ip' patches applied.

If I do an 'ip ru show', then I see lots of tables, though not all it seems. (I have not tried beyond 205 yet). But, if I do an 'ip route show table XX', then I see nothing or incorrect values.

For my test, I am creating 200 virtual interfaces (mac-vlans in my case, but 802.1q should work equally well.) I am giving them all IP addrs on the same subnet, and a routing table for each source IP addr.

The commands I run to generate the routing tables are found in this file:
http://www.candelatech.com/oss/gc.txt

When I change back to kernel 2.6.16.16 with only my patchset applied, things seem to be working, so it looks like an issue with the new kernel patches. I can provide access to this machine as well as my full patch set, etc...

For whatever reason, table 5 does appear in a bizarre fashion:

[greear@grok lanforge]$ more ~/tmp/ip.txt [root@sb65g2 lanforge]# ip route show table 5 10.1.2.0/24 via 10.1.2.2 dev eth1#0 default via 10.1.2.1 dev eth1#0 [root@sb65g2 lanforge]# ip route show table 4 [root@sb65g2 lanforge]# ip route show table 3 [root@sb65g2 lanforge]# ip route show table 2 [root@sb65g2 lanforge]# ip route show table 1 [root@sb65g2 lanforge]# ip route show table 0 10.1.2.0/24 via 10.1.2.2 dev eth1#0 table 5 default via 10.1.2.1 dev eth1#0 table 5

# Here is a listing of 'ip ru show'. [greear@grok lanforge]$ more ~/tmp/ru.txt

0:      from all lookup local
31203:  from 10.1.2.144 lookup 147
31204:  from 10.1.2.143 lookup 146
31205:  from 10.1.2.142 lookup 145
31206:  from 10.1.2.141 lookup 144
31207:  from 10.1.2.140 lookup 143
31208:  from 10.1.2.139 lookup 142
31209:  from 10.1.2.138 lookup 141
31210:  from 10.1.2.137 lookup 140
31211:  from 10.1.2.136 lookup 139
31212:  from 10.1.2.135 lookup 138
31213:  from 10.1.2.134 lookup 137
31214:  from 10.1.2.133 lookup 136
31215:  from 10.1.2.132 lookup 135
31216:  from 10.1.2.131 lookup 134
31217:  from 10.1.2.130 lookup 133
31218:  from 10.1.2.129 lookup 132
31219:  from 10.1.2.128 lookup 131
31220:  from 10.1.2.127 lookup 130
31221:  from 10.1.2.126 lookup 129
31222:  from 10.1.2.125 lookup 128
31223:  from 10.1.2.124 lookup 127
31224:  from 10.1.2.123 lookup 126
31225:  from 10.1.2.122 lookup 125
31226:  from 10.1.2.121 lookup 124
31227:  from 10.1.2.120 lookup 123
31228:  from 10.1.2.119 lookup 122
31229:  from 10.1.2.118 lookup 121
31230:  from 10.1.2.117 lookup 120
31231:  from 10.1.2.116 lookup 119
31232:  from 10.1.2.115 lookup 118
31233:  from 10.1.2.114 lookup 117
31234:  from 10.1.2.113 lookup 116
31235:  from 10.1.2.201 lookup 204
31236:  from 10.1.2.200 lookup 203
31237:  from 10.1.2.199 lookup 202
31238:  from 10.1.2.198 lookup 201
31239:  from 10.1.2.197 lookup 200
31240:  from 10.1.2.196 lookup 199
31241:  from 10.1.2.195 lookup 198
31242:  from 10.1.2.112 lookup 115
31243:  from 10.1.2.111 lookup 114
31244:  from 10.1.2.110 lookup 113
31245:  from 10.1.2.109 lookup 112
31246:  from 10.1.2.108 lookup 111
31247:  from 10.1.2.107 lookup 110
31248:  from 10.1.2.106 lookup 109
31249:  from 10.1.2.105 lookup 108
31250:  from 10.1.2.104 lookup 107
31251:  from 10.1.2.103 lookup 106
31252:  from 10.1.2.102 lookup 105
31253:  from 10.1.2.101 lookup 104
31254:  from 10.1.2.100 lookup 103
31255:  from 10.1.2.99 lookup 102
31256:  from 10.1.2.98 lookup 101
31257:  from 10.1.2.97 lookup 100
31258:  from 10.1.2.96 lookup 99
31259:  from 10.1.2.95 lookup 98
31260:  from 10.1.2.94 lookup 97
31261:  from 10.1.2.93 lookup 96
31262:  from 10.1.2.92 lookup 95
31263:  from 10.1.2.91 lookup 94
31264:  from 10.1.2.90 lookup 93
31265:  from 10.1.2.89 lookup 92
31266:  from 10.1.2.88 lookup 91
31267:  from 10.1.2.87 lookup 90
31268:  from 10.1.2.86 lookup 89
31269:  from 10.1.2.85 lookup 88
31270:  from 10.1.2.84 lookup 87
31271:  from 10.1.2.83 lookup 86
31272:  from 10.1.2.82 lookup 85
31273:  from 10.1.2.81 lookup 84
31274:  from 10.1.2.80 lookup 83
31275:  from 10.1.2.79 lookup 82

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
#14 lore raw
Quoted 9 lines · Ben Greear
Quoted 2 lines · Patrick McHardy
Quoted 2 lines

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

I am seeing problems..though they could be with the way I'm using the tool or pehaps I patched the kernel incorrectly.

Quoted 7 lines

I applied the 3 patches to 2.6.17..all patches applied without problem, but with a few lines of fuzz. I get the same behaviour with and without the new 'ip' patches applied.

If I do an 'ip ru show', then I see lots of tables, though not all it seems. (I have not tried beyond 205 yet). But, if I do an 'ip route show table XX', then I see nothing or incorrect values.

My patches introduced a bug when dumping tables which could lead to incorrect routes beeing dumped. A second bug (that already existed) makes the kernel fail when dumping more rules than fit in a skb. I think I've already seen the patch to address the second problem a short time ago sent by someone else. Anyway, this patch should fix both.

net/ipv4/fib_frontend.c +5 -3
index 3c49e6b..6e1aaa4 100644
@@ -357,6 +357,7 @@ int inet_dump_fib(struct sk_buff *skb, s
 	unsigned int e = 0, s_e;
 	struct fib_table *tb;
 	struct hlist_node *node;
+	int dumped = 0;
 
 	if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) &&
 	    ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED)
@@ -365,16 +366,17 @@ int inet_dump_fib(struct sk_buff *skb, s
 	s_h = cb->args[0];
 	s_e = cb->args[1];
 
-	for (h = s_h; h < FIB_TABLE_HASHSZ; h++) {
+	for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
 		e = 0;
 		hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) {
 			if (e < s_e)
 				goto next;
-			if (e > s_e)
-				memset(&cb->args[1], 0, sizeof(cb->args) -
+			if (dumped)
+				memset(&cb->args[2], 0, sizeof(cb->args) -
 				                 2 * sizeof(cb->args[0]));
 			if (tb->tb_dump(tb, skb, cb) < 0) 
 				goto out;
+			dumped = 1;
 next:
 			e++;
 		}
net/ipv4/fib_rules.c +2 -2
index a41ab4b..6f33f12 100644
@@ -459,13 +459,13 @@ int inet_dump_rules(struct sk_buff *skb,
 
 	rcu_read_lock();
 	hlist_for_each_entry(r, node, &fib_rules, hlist) {
-
 		if (idx < s_idx)
-			continue;
+			goto next;
 		if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid,
 				   cb->nlh->nlmsg_seq,
 				   RTM_NEWRULE, NLM_F_MULTI) < 0)
 			break;
+next:
 		idx++;
 	}
 	rcu_read_unlock();
maintainer
#15 lore raw

From: Patrick McHardy <[email protected]>
Date: Fri, 07 Jul 2006 21:58:31 +0200

Quoted 6 lines

My patches introduced a bug when dumping tables which could lead to incorrect routes beeing dumped. A second bug (that already existed) makes the kernel fail when dumping more rules than fit in a skb. I think I've already seen the patch to address the second problem a short time ago sent by someone else. Anyway, this patch should fix both.

Nice work Patrick.

You guys have a lot of time to flesh out any remaining issues and failures, and then submit this for 2.6.19

Thanks again.

#16 lore raw
Quoted 4 lines · David Miller

Nice work Patrick.

You guys have a lot of time to flesh out any remaining issues and failures, and then submit this for 2.6.19

Will do, I already expected to miss the deadline :)

#17 lore raw
In reply to Patrick McHardy
Quoted 21 lines · Patrick McHardy
Quoted 10 lines · Ben Greear
Quoted 2 lines · Patrick McHardy
Quoted 2 lines

I took on Ben's challenge to increase the number of possible routing tables, these are the resulting patches.

I am seeing problems..though they could be with the way I'm using the tool or pehaps I patched the kernel incorrectly.

Quoted 7 lines

I applied the 3 patches to 2.6.17..all patches applied without problem, but with a few lines of fuzz. I get the same behaviour with and without the new 'ip' patches applied.

If I do an 'ip ru show', then I see lots of tables, though not all it seems. (I have not tried beyond 205 yet). But, if I do an 'ip route show table XX', then I see nothing or incorrect values.

Quoted 6 lines

My patches introduced a bug when dumping tables which could lead to incorrect routes beeing dumped. A second bug (that already existed) makes the kernel fail when dumping more rules than fit in a skb. I think I've already seen the patch to address the second problem a short time ago sent by someone else. Anyway, this patch should fix both.

With this patch applied everything is looking much better. I currently have 400+ interfaces and one routing table per interface, and traffic is passing as expected.

This is probably due to my own application polling interfaces for
stat updates...but I am seeing over 50% usage (with more system than user-space) in this setup on an otherwise lightly loaded system. top shows no process averaging more than about 2% CPU (and only 2-3 are above 0.0 typically), which I find a little strange. load is around 3.0.

I'll dig into my code and see if I can tune the stat-gathering logic a bit...

Thanks,
Ben

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com
#18 lore raw
Quoted 11 lines · Ben Greear

With this patch applied everything is looking much better. I currently have 400+ interfaces and one routing table per interface, and traffic is passing as expected.

This is probably due to my own application polling interfaces for stat updates...but I am seeing over 50% usage (with more system than user-space)
in this setup on an otherwise lightly loaded system. top shows no process averaging
more than about 2% CPU (and only 2-3 are above 0.0 typically), which I find a little strange. load is around 3.0.

I can't imagine this beeing related to the increased number of routing tables, with a number of entries slightly (not even two times) over the hash size it shouldn't make that much of a difference. It may of course be a bug, but I don't see it.

#19 lore raw
Quoted 15 lines · Patrick McHardy
Quoted 11 lines · Ben Greear

With this patch applied everything is looking much better. I currently have 400+ interfaces and one routing table per interface, and traffic is passing as expected.

This is probably due to my own application polling interfaces for stat updates...but I am seeing over 50% usage (with more system than user-space)
in this setup on an otherwise lightly loaded system. top shows no process averaging
more than about 2% CPU (and only 2-3 are above 0.0 typically), which I find a little strange. load is around 3.0.

Quoted 4 lines

I can't imagine this beeing related to the increased number of routing tables, with a number of entries slightly (not even two times) over the hash size it shouldn't make that much of a difference. It may of course be a bug, but I don't see it.

I think it was my polling logic that was the problem. I fixed it up to be more clever and the load went away.

Ben

Quoted 6 lines

-
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com