Commit 34e95647 authored by Patrick McHardy's avatar Patrick McHardy Committed by Stephen Hemminger

Add support for larger number of routing tables

[IPROUTE]: Add support for larger number of routing tables

Support support for 2^32 routing tables by using the new RTA_TABLE
attribute for specifying tables > 255 and intepreting it if it is
sent by the kernel.

When tables > 255 are used on a kernel not supporting it an error will
occur because of the unknown netlink attribute.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarStephen Hemminger <shemminger@osdl.org>
parent 9c47d877
...@@ -238,9 +238,8 @@ enum rt_class_t ...@@ -238,9 +238,8 @@ enum rt_class_t
RT_TABLE_DEFAULT=253, RT_TABLE_DEFAULT=253,
RT_TABLE_MAIN=254, RT_TABLE_MAIN=254,
RT_TABLE_LOCAL=255, RT_TABLE_LOCAL=255,
__RT_TABLE_MAX RT_TABLE_MAX=0xFFFFFFFF,
}; };
#define RT_TABLE_MAX (__RT_TABLE_MAX - 1)
...@@ -263,6 +262,7 @@ enum rtattr_type_t ...@@ -263,6 +262,7 @@ enum rtattr_type_t
RTA_CACHEINFO, RTA_CACHEINFO,
RTA_SESSION, RTA_SESSION,
RTA_MP_ALGO, RTA_MP_ALGO,
RTA_TABLE,
__RTA_MAX __RTA_MAX
}; };
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
char* rtnl_rtprot_n2a(int id, char *buf, int len); char* rtnl_rtprot_n2a(int id, char *buf, int len);
char* rtnl_rtscope_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_rtrealm_n2a(int id, char *buf, int len);
char* rtnl_dsfield_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); int rtnl_rtprot_a2n(__u32 *id, char *arg);
......
...@@ -32,4 +32,12 @@ extern int do_multiaddr(int argc, char **argv); ...@@ -32,4 +32,12 @@ extern int do_multiaddr(int argc, char **argv);
extern int do_multiroute(int argc, char **argv); extern int do_multiroute(int argc, char **argv);
extern int do_xfrm(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; extern struct rtnl_handle rth;
...@@ -140,6 +140,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) ...@@ -140,6 +140,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
inet_prefix via; inet_prefix via;
int host_len = -1; int host_len = -1;
static int ip6_multiple_tables; static int ip6_multiple_tables;
__u32 table;
SPRINT_BUF(b1); SPRINT_BUF(b1);
...@@ -165,7 +166,10 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) ...@@ -165,7 +166,10 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
else if (r->rtm_family == AF_IPX) else if (r->rtm_family == AF_IPX)
host_len = 80; host_len = 80;
if (r->rtm_family == AF_INET6 && r->rtm_table != RT_TABLE_MAIN) parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
table = rtm_get_table(r, tb);
if (r->rtm_family == AF_INET6 && table != RT_TABLE_MAIN)
ip6_multiple_tables = 1; ip6_multiple_tables = 1;
if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) { if (r->rtm_family == AF_INET6 && !ip6_multiple_tables) {
...@@ -187,7 +191,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) ...@@ -187,7 +191,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
} }
} }
} else { } else {
if (filter.tb > 0 && filter.tb != r->rtm_table) if (filter.tb > 0 && filter.tb != table)
return 0; return 0;
} }
if ((filter.protocol^r->rtm_protocol)&filter.protocolmask) if ((filter.protocol^r->rtm_protocol)&filter.protocolmask)
...@@ -217,8 +221,6 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) ...@@ -217,8 +221,6 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family) if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family)
return 0; return 0;
parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);
memset(&dst, 0, sizeof(dst)); memset(&dst, 0, sizeof(dst));
dst.family = r->rtm_family; dst.family = r->rtm_family;
if (tb[RTA_DST]) if (tb[RTA_DST])
...@@ -371,8 +373,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) ...@@ -371,8 +373,8 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF]))); fprintf(fp, "dev %s ", ll_index_to_name(*(int*)RTA_DATA(tb[RTA_OIF])));
if (!(r->rtm_flags&RTM_F_CLONED)) { if (!(r->rtm_flags&RTM_F_CLONED)) {
if (r->rtm_table != RT_TABLE_MAIN && !filter.tb) if (table != RT_TABLE_MAIN && !filter.tb)
fprintf(fp, " table %s ", rtnl_rttable_n2a(r->rtm_table, b1, sizeof(b1))); fprintf(fp, " table %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
if (r->rtm_protocol != RTPROT_BOOT && filter.protocolmask != -1) if (r->rtm_protocol != RTPROT_BOOT && filter.protocolmask != -1)
fprintf(fp, " proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1))); fprintf(fp, " proto %s ", rtnl_rtprot_n2a(r->rtm_protocol, b1, sizeof(b1)));
if (r->rtm_scope != RT_SCOPE_UNIVERSE && filter.scopemask != -1) if (r->rtm_scope != RT_SCOPE_UNIVERSE && filter.scopemask != -1)
...@@ -875,7 +877,12 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv) ...@@ -875,7 +877,12 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv)
NEXT_ARG(); NEXT_ARG();
if (rtnl_rttable_a2n(&tid, *argv)) if (rtnl_rttable_a2n(&tid, *argv))
invarg("\"table\" value is invalid\n", *argv); invarg("\"table\" value is invalid\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; table_ok = 1;
} else if (strcmp(*argv, "dev") == 0 || } else if (strcmp(*argv, "dev") == 0 ||
strcmp(*argv, "oif") == 0) { strcmp(*argv, "oif") == 0) {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "rt_names.h" #include "rt_names.h"
#include "utils.h" #include "utils.h"
#include "ip_common.h"
extern struct rtnl_handle rth; extern struct rtnl_handle rth;
...@@ -51,6 +52,7 @@ static int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, ...@@ -51,6 +52,7 @@ static int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n,
struct rtmsg *r = NLMSG_DATA(n); struct rtmsg *r = NLMSG_DATA(n);
int len = n->nlmsg_len; int len = n->nlmsg_len;
int host_len = -1; int host_len = -1;
__u32 table;
struct rtattr * tb[RTA_MAX+1]; struct rtattr * tb[RTA_MAX+1];
char abuf[256]; char abuf[256];
SPRINT_BUF(b1); SPRINT_BUF(b1);
...@@ -129,8 +131,9 @@ static int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, ...@@ -129,8 +131,9 @@ static int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n,
fprintf(fp, "iif %s ", (char*)RTA_DATA(tb[RTA_IIF])); fprintf(fp, "iif %s ", (char*)RTA_DATA(tb[RTA_IIF]));
} }
if (r->rtm_table) table = rtm_get_table(r, tb);
fprintf(fp, "lookup %s ", rtnl_rttable_n2a(r->rtm_table, b1, sizeof(b1))); if (table)
fprintf(fp, "lookup %s ", rtnl_rttable_n2a(table, b1, sizeof(b1)));
if (tb[RTA_FLOW]) { if (tb[RTA_FLOW]) {
__u32 to = *(__u32*)RTA_DATA(tb[RTA_FLOW]); __u32 to = *(__u32*)RTA_DATA(tb[RTA_FLOW]);
...@@ -257,7 +260,12 @@ static int iprule_modify(int cmd, int argc, char **argv) ...@@ -257,7 +260,12 @@ static int iprule_modify(int cmd, int argc, char **argv)
NEXT_ARG(); NEXT_ARG();
if (rtnl_rttable_a2n(&tid, *argv)) if (rtnl_rttable_a2n(&tid, *argv))
invarg("invalid table ID\n", *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; table_ok = 1;
} else if (strcmp(*argv, "dev") == 0 || } else if (strcmp(*argv, "dev") == 0 ||
strcmp(*argv, "iif") == 0) { strcmp(*argv, "iif") == 0) {
......
...@@ -329,7 +329,7 @@ static void rtnl_rttable_initialize(void) ...@@ -329,7 +329,7 @@ static void rtnl_rttable_initialize(void)
rtnl_rttable_hash, 256); rtnl_rttable_hash, 256);
} }
char * rtnl_rttable_n2a(int id, char *buf, int len) char * rtnl_rttable_n2a(__u32 id, char *buf, int len)
{ {
struct rtnl_hash_entry *entry; struct rtnl_hash_entry *entry;
...@@ -354,7 +354,7 @@ int rtnl_rttable_a2n(__u32 *id, char *arg) ...@@ -354,7 +354,7 @@ int rtnl_rttable_a2n(__u32 *id, char *arg)
static unsigned long res; static unsigned long res;
struct rtnl_hash_entry *entry; struct rtnl_hash_entry *entry;
char *end; char *end;
int i; __u32 i;
if (cache && strcmp(cache, arg) == 0) { if (cache && strcmp(cache, arg) == 0) {
*id = res; *id = res;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment