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: Patrick McHardy <kaber@trash.net> Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
This commit is contained in:
parent
9c47d877d8
commit
34e9564753
|
|
@ -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
|
||||||
RTA_CACHEINFO,
|
RTA_CACHEINFO,
|
||||||
RTA_SESSION,
|
RTA_SESSION,
|
||||||
RTA_MP_ALGO,
|
RTA_MP_ALGO,
|
||||||
|
RTA_TABLE,
|
||||||
__RTA_MAX
|
__RTA_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
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;
|
||||||
|
|
|
||||||
21
ip/iproute.c
21
ip/iproute.c
|
|
@ -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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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)
|
||||||
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)
|
||||||
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)
|
||||||
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) {
|
||||||
|
|
|
||||||
14
ip/iprule.c
14
ip/iprule.c
|
|
@ -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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue