Netlink: Allow more than 256 routing tables.
Since 2.6.19, the netlink API defines RTA_TABLE routing attribute to allow 32-bit routing table IDs. Using this attribute to index routing tables at Linux, instead of 8-bit rtm_table field.
This commit is contained in:
parent
86b4e17001
commit
9ddbfbddf8
7 changed files with 82 additions and 40 deletions
|
@ -970,13 +970,15 @@ krt_sock_close_shared(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
krt_sys_start(struct krt_proto *p)
|
krt_sys_start(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
krt_table_map[KRT_CF->sys.table_id] = p;
|
krt_table_map[KRT_CF->sys.table_id] = p;
|
||||||
|
|
||||||
krt_sock_open_shared();
|
krt_sock_open_shared();
|
||||||
p->sys.sk = krt_sock;
|
p->sys.sk = krt_sock;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -992,10 +994,11 @@ krt_sys_shutdown(struct krt_proto *p)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void
|
int
|
||||||
krt_sys_start(struct krt_proto *p)
|
krt_sys_start(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
p->sys.sk = krt_sock_open(p->p.pool, p, KRT_CF->sys.table_id);
|
p->sys.sk = krt_sock_open(p->p.pool, p, KRT_CF->sys.table_id);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct krt_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline void krt_sys_io_init(void) { }
|
||||||
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
||||||
|
|
||||||
static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { }
|
static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { }
|
||||||
|
|
|
@ -84,18 +84,18 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; }
|
||||||
#define EA_KRT_FEATURE_ALLFRAG EA_KRT_FEATURES | EA_BIT(0x3)
|
#define EA_KRT_FEATURE_ALLFRAG EA_KRT_FEATURES | EA_BIT(0x3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define NL_NUM_TABLES 256
|
|
||||||
|
|
||||||
struct krt_params {
|
struct krt_params {
|
||||||
int table_id; /* Kernel table ID we sync with */
|
u32 table_id; /* Kernel table ID we sync with */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct krt_state {
|
struct krt_state {
|
||||||
|
struct krt_proto *hash_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
||||||
|
static inline void krt_sys_preconfig(struct config *c UNUSED) { }
|
||||||
|
static inline void krt_sys_postconfig(struct krt_config *x UNUSED) { }
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,8 +23,6 @@ CF_ADDTO(kern_proto, kern_proto kern_sys_item ';')
|
||||||
|
|
||||||
kern_sys_item:
|
kern_sys_item:
|
||||||
KERNEL TABLE expr {
|
KERNEL TABLE expr {
|
||||||
if ($3 <= 0 || $3 >= NL_NUM_TABLES)
|
|
||||||
cf_error("Kernel routing table number out of range");
|
|
||||||
THIS_KRT->sys.table_id = $3;
|
THIS_KRT->sys.table_id = $3;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "lib/krt.h"
|
#include "lib/krt.h"
|
||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
#include "lib/hash.h"
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
|
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
|
#ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
|
||||||
#define MSG_TRUNC 0x20
|
#define MSG_TRUNC 0x20
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,6 +42,11 @@
|
||||||
#define IFF_LOWER_UP 0x10000
|
#define IFF_LOWER_UP 0x10000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef RTA_TABLE
|
||||||
|
#define RTA_TABLE 15
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Synchronous Netlink interface
|
* Synchronous Netlink interface
|
||||||
*/
|
*/
|
||||||
|
@ -650,7 +657,23 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
||||||
* Routes
|
* Routes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct krt_proto *nl_table_map[NL_NUM_TABLES];
|
static inline u32
|
||||||
|
krt_table_id(struct krt_proto *p)
|
||||||
|
{
|
||||||
|
return KRT_CF->sys.table_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HASH(struct krt_proto) nl_table_map;
|
||||||
|
|
||||||
|
#define RTH_FN(k) u32_hash(k)
|
||||||
|
#define RTH_EQ(k1,k2) k1 == k2
|
||||||
|
#define RTH_KEY(p) krt_table_id(p)
|
||||||
|
#define RTH_NEXT(p) p->sys.hash_next
|
||||||
|
|
||||||
|
#define RTH_REHASH rth_rehash
|
||||||
|
#define RTH_PARAMS /8, *2, 2, 2, 6, 20
|
||||||
|
|
||||||
|
HASH_DEFINE_REHASH_FN(RTH, struct krt_proto)
|
||||||
|
|
||||||
int
|
int
|
||||||
krt_capable(rte *e)
|
krt_capable(rte *e)
|
||||||
|
@ -708,12 +731,15 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||||
|
|
||||||
r.r.rtm_family = BIRD_AF;
|
r.r.rtm_family = BIRD_AF;
|
||||||
r.r.rtm_dst_len = net->n.pxlen;
|
r.r.rtm_dst_len = net->n.pxlen;
|
||||||
r.r.rtm_tos = 0;
|
|
||||||
r.r.rtm_table = KRT_CF->sys.table_id;
|
|
||||||
r.r.rtm_protocol = RTPROT_BIRD;
|
r.r.rtm_protocol = RTPROT_BIRD;
|
||||||
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
|
||||||
|
|
||||||
|
if (krt_table_id(p) < 256)
|
||||||
|
r.r.rtm_table = krt_table_id(p);
|
||||||
|
else
|
||||||
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_TABLE, krt_table_id(p));
|
||||||
|
|
||||||
/* For route delete, we do not specify route attributes */
|
/* For route delete, we do not specify route attributes */
|
||||||
if (!new)
|
if (!new)
|
||||||
return nl_exchange(&r.h);
|
return nl_exchange(&r.h);
|
||||||
|
@ -809,11 +835,12 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
{
|
{
|
||||||
struct krt_proto *p;
|
struct krt_proto *p;
|
||||||
struct rtmsg *i;
|
struct rtmsg *i;
|
||||||
struct rtattr *a[RTA_CACHEINFO+1];
|
struct rtattr *a[RTA_TABLE+1];
|
||||||
int new = h->nlmsg_type == RTM_NEWROUTE;
|
int new = h->nlmsg_type == RTM_NEWROUTE;
|
||||||
|
|
||||||
ip_addr dst = IPA_NONE;
|
ip_addr dst = IPA_NONE;
|
||||||
u32 oif = ~0;
|
u32 oif = ~0;
|
||||||
|
u32 table;
|
||||||
int src;
|
int src;
|
||||||
|
|
||||||
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
|
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
|
||||||
|
@ -825,6 +852,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
||||||
#endif
|
#endif
|
||||||
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
||||||
|
(a[RTA_TABLE] && RTA_PAYLOAD(a[RTA_TABLE]) != 4) ||
|
||||||
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
|
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
|
||||||
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
||||||
(a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
|
(a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
|
||||||
|
@ -843,10 +871,15 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
if (a[RTA_OIF])
|
if (a[RTA_OIF])
|
||||||
oif = rta_get_u32(a[RTA_OIF]);
|
oif = rta_get_u32(a[RTA_OIF]);
|
||||||
|
|
||||||
p = nl_table_map[i->rtm_table]; /* Do we know this table? */
|
if (a[RTA_TABLE])
|
||||||
DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p ? p->p.name : "(none)");
|
table = rta_get_u32(a[RTA_TABLE]);
|
||||||
|
else
|
||||||
|
table = i->rtm_table;
|
||||||
|
|
||||||
|
p = HASH_FIND(nl_table_map, RTH, table); /* Do we know this table? */
|
||||||
|
DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, table, i->rtm_protocol, p ? p->p.name : "(none)");
|
||||||
if (!p)
|
if (!p)
|
||||||
SKIP("unknown table %d\n", i->rtm_table);
|
SKIP("unknown table %d\n", table);
|
||||||
|
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
|
@ -1186,25 +1219,41 @@ nl_open_async(void)
|
||||||
bug("Netlink: sk_open failed");
|
bug("Netlink: sk_open failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interface to the UNIX krt module
|
* Interface to the UNIX krt module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
|
|
||||||
|
|
||||||
void
|
void
|
||||||
|
krt_sys_io_init(void)
|
||||||
|
{
|
||||||
|
HASH_INIT(nl_table_map, krt_pool, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
krt_sys_start(struct krt_proto *p)
|
krt_sys_start(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
nl_table_map[KRT_CF->sys.table_id] = p;
|
struct krt_proto *old = HASH_FIND(nl_table_map, RTH, krt_table_id(p));
|
||||||
|
|
||||||
|
if (old)
|
||||||
|
{
|
||||||
|
log(L_ERR "%s: Kernel table %u already registered by %s",
|
||||||
|
p->p.name, krt_table_id(p), old->p.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HASH_INSERT2(nl_table_map, RTH, krt_pool, p);
|
||||||
|
|
||||||
nl_open();
|
nl_open();
|
||||||
nl_open_async();
|
nl_open_async();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_sys_shutdown(struct krt_proto *p UNUSED)
|
krt_sys_shutdown(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
nl_table_map[KRT_CF->sys.table_id] = NULL;
|
HASH_REMOVE2(nl_table_map, RTH, krt_pool, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1213,23 +1262,6 @@ krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt
|
||||||
return n->sys.table_id == o->sys.table_id;
|
return n->sys.table_id == o->sys.table_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_sys_preconfig(struct config *c UNUSED)
|
|
||||||
{
|
|
||||||
bzero(&nl_cf_table, sizeof(nl_cf_table));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
krt_sys_postconfig(struct krt_config *x)
|
|
||||||
{
|
|
||||||
int id = x->sys.table_id;
|
|
||||||
|
|
||||||
if (nl_cf_table[id/8] & (1 << (id%8)))
|
|
||||||
cf_error("Multiple kernel syncers defined for table #%d", id);
|
|
||||||
nl_cf_table[id/8] |= (1 << (id%8));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_sys_init_config(struct krt_config *cf)
|
krt_sys_init_config(struct krt_config *cf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -77,6 +77,7 @@ krt_io_init(void)
|
||||||
krt_pool = rp_new(&root_pool, "Kernel Syncer");
|
krt_pool = rp_new(&root_pool, "Kernel Syncer");
|
||||||
krt_filter_lp = lp_new(krt_pool, 4080);
|
krt_filter_lp = lp_new(krt_pool, 4080);
|
||||||
init_list(&krt_proto_list);
|
init_list(&krt_proto_list);
|
||||||
|
krt_sys_io_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1126,7 +1127,11 @@ krt_start(struct proto *P)
|
||||||
krt_learn_init(p);
|
krt_learn_init(p);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
krt_sys_start(p);
|
if (!krt_sys_start(p))
|
||||||
|
{
|
||||||
|
rem_node(&p->krt_node);
|
||||||
|
return PS_START;
|
||||||
|
}
|
||||||
|
|
||||||
krt_scan_timer_start(p);
|
krt_scan_timer_start(p);
|
||||||
|
|
||||||
|
@ -1150,8 +1155,10 @@ krt_shutdown(struct proto *P)
|
||||||
p->ready = 0;
|
p->ready = 0;
|
||||||
p->initialized = 0;
|
p->initialized = 0;
|
||||||
|
|
||||||
krt_sys_shutdown(p);
|
if (p->p.proto_state == PS_START)
|
||||||
|
return PS_DOWN;
|
||||||
|
|
||||||
|
krt_sys_shutdown(p);
|
||||||
rem_node(&p->krt_node);
|
rem_node(&p->krt_node);
|
||||||
|
|
||||||
return PS_DOWN;
|
return PS_DOWN;
|
||||||
|
|
|
@ -119,8 +119,9 @@ struct proto_config * krt_init_config(int class);
|
||||||
|
|
||||||
/* krt sysdep */
|
/* krt sysdep */
|
||||||
|
|
||||||
|
void krt_sys_io_init(void);
|
||||||
void krt_sys_init(struct krt_proto *);
|
void krt_sys_init(struct krt_proto *);
|
||||||
void krt_sys_start(struct krt_proto *);
|
int krt_sys_start(struct krt_proto *);
|
||||||
void krt_sys_shutdown(struct krt_proto *);
|
void krt_sys_shutdown(struct krt_proto *);
|
||||||
int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o);
|
int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue