mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Adds support for several Linux kernel route attributes.
This commit is contained in:
parent
4aef102be1
commit
71ca77169d
@ -1420,12 +1420,20 @@ device routes from BIRD tables to kernel routing tables is restricted
|
|||||||
to prevent accidental interference. This restriction can be disabled using
|
to prevent accidental interference. This restriction can be disabled using
|
||||||
<cf/device routes/ switch.
|
<cf/device routes/ switch.
|
||||||
|
|
||||||
<p>If your OS supports only a single routing table, you can configure only one
|
<p>If your OS supports only a single routing table, you can configure
|
||||||
instance of the Kernel protocol. If it supports multiple tables (in order to
|
only one instance of the Kernel protocol. If it supports multiple
|
||||||
allow policy routing; such an OS is for example Linux 2.2), you can run as many instances as you want, but each of
|
tables (in order to allow policy routing; such an OS is for example
|
||||||
them must be connected to a different BIRD routing table and to a different
|
Linux), you can run as many instances as you want, but each of them
|
||||||
|
must be connected to a different BIRD routing table and to a different
|
||||||
kernel table.
|
kernel table.
|
||||||
|
|
||||||
|
<p>Because the kernel protocol is partially integrated with the
|
||||||
|
connected routing table, there are two limitations - it is not
|
||||||
|
possible to connect more kernel protocols to the same routing table
|
||||||
|
and changing route attributes (even the kernel ones) in an export
|
||||||
|
filter of a kernel protocol does not work. Both limitations can be
|
||||||
|
overcome using another routing table and the pipe protocol.
|
||||||
|
|
||||||
<sect1>Configuration
|
<sect1>Configuration
|
||||||
|
|
||||||
<p><descrip>
|
<p><descrip>
|
||||||
@ -1450,12 +1458,27 @@ kernel table.
|
|||||||
only on systems supporting multiple routing tables.
|
only on systems supporting multiple routing tables.
|
||||||
</descrip>
|
</descrip>
|
||||||
|
|
||||||
<p>The Kernel protocol doesn't define any route attributes.
|
<sect1>Attributes
|
||||||
|
|
||||||
|
<p>The Kernel protocol defines several attributes. These attributes
|
||||||
|
are translated to appropriate system (and OS-specific) route attributes.
|
||||||
|
We support these attributes:
|
||||||
|
|
||||||
|
<descrip>
|
||||||
|
<tag>ip <cf/krt_prefsrc/</tag> (Linux) The preferred source address.
|
||||||
|
Used in source address selection for outgoing packets. Have to
|
||||||
|
be one of IP addresses of the router.
|
||||||
|
|
||||||
|
<tag>int <cf/krt_realm/</tag> (Linux) The realm of the route. Can be
|
||||||
|
used for traffic classification.
|
||||||
|
</descrip>
|
||||||
|
|
||||||
|
<sect1>Example
|
||||||
|
|
||||||
<p>A simple configuration can look this way:
|
<p>A simple configuration can look this way:
|
||||||
|
|
||||||
<p><code>
|
<p><code>
|
||||||
protocol kernel {
|
protocol kernel {
|
||||||
import all;
|
|
||||||
export all;
|
export all;
|
||||||
}
|
}
|
||||||
</code>
|
</code>
|
||||||
|
@ -344,7 +344,8 @@ typedef struct eattr {
|
|||||||
#define EAP_BGP 1 /* BGP attributes */
|
#define EAP_BGP 1 /* BGP attributes */
|
||||||
#define EAP_RIP 2 /* RIP */
|
#define EAP_RIP 2 /* RIP */
|
||||||
#define EAP_OSPF 3 /* OSPF */
|
#define EAP_OSPF 3 /* OSPF */
|
||||||
#define EAP_MAX 4
|
#define EAP_KRT 4 /* Kernel route attributes */
|
||||||
|
#define EAP_MAX 5
|
||||||
|
|
||||||
#define EA_CODE(proto,id) (((proto) << 8) | (id))
|
#define EA_CODE(proto,id) (((proto) << 8) | (id))
|
||||||
#define EA_PROTO(ea) ((ea) >> 8)
|
#define EA_PROTO(ea) ((ea) >> 8)
|
||||||
|
@ -10,7 +10,7 @@ CF_HDR
|
|||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(ASYNC, KERNEL, TABLE)
|
CF_KEYWORDS(ASYNC, KERNEL, TABLE, KRT_PREFSRC, KRT_REALM)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
@ -24,6 +24,9 @@ nl_item:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
CF_ADDTO(dynamic_attr, KRT_PREFSRC { $$ = f_new_dynamic_attr(EAF_TYPE_IP_ADDRESS, T_IP, EA_KRT_PREFSRC); })
|
||||||
|
CF_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); })
|
||||||
|
|
||||||
CF_CODE
|
CF_CODE
|
||||||
|
|
||||||
CF_END
|
CF_END
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
#include "lib/alloca.h"
|
||||||
#include "lib/timer.h"
|
#include "lib/timer.h"
|
||||||
#include "lib/unix.h"
|
#include "lib/unix.h"
|
||||||
#include "lib/krt.h"
|
#include "lib/krt.h"
|
||||||
@ -618,6 +619,7 @@ nh_bufsize(struct mpnh *nh)
|
|||||||
static void
|
static void
|
||||||
nl_send_route(struct krt_proto *p, rte *e, int new)
|
nl_send_route(struct krt_proto *p, rte *e, int new)
|
||||||
{
|
{
|
||||||
|
eattr *ea;
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
struct {
|
struct {
|
||||||
@ -641,6 +643,13 @@ nl_send_route(struct krt_proto *p, rte *e, int new)
|
|||||||
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 (ea = ea_find(a->eattrs, EA_KRT_PREFSRC))
|
||||||
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
|
||||||
|
|
||||||
|
if (ea = ea_find(a->eattrs, EA_KRT_REALM))
|
||||||
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
case RTD_ROUTER:
|
case RTD_ROUTER:
|
||||||
@ -698,10 +707,9 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|||||||
struct rtmsg *i;
|
struct rtmsg *i;
|
||||||
struct rtattr *a[RTA_CACHEINFO+1];
|
struct rtattr *a[RTA_CACHEINFO+1];
|
||||||
int new = h->nlmsg_type == RTM_NEWROUTE;
|
int new = h->nlmsg_type == RTM_NEWROUTE;
|
||||||
ip_addr dst;
|
|
||||||
rte *e;
|
ip_addr dst = IPA_NONE;
|
||||||
net *net;
|
u32 oif = ~0;
|
||||||
u32 oif;
|
|
||||||
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)))
|
||||||
@ -709,12 +717,14 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|||||||
if (i->rtm_family != BIRD_AF)
|
if (i->rtm_family != BIRD_AF)
|
||||||
return;
|
return;
|
||||||
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
|
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
|
||||||
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
|
||||||
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
||||||
#endif
|
#endif
|
||||||
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
|
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
||||||
|
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
|
||||||
|
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
||||||
|
(a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
|
||||||
|
(a[RTA_FLOW] && RTA_PAYLOAD(a[RTA_OIF]) != 4))
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Malformed message received");
|
log(L_ERR "KRT: Malformed message received");
|
||||||
return;
|
return;
|
||||||
@ -725,13 +735,9 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|||||||
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
|
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
|
||||||
ipa_ntoh(dst);
|
ipa_ntoh(dst);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
dst = IPA_NONE;
|
|
||||||
|
|
||||||
if (a[RTA_OIF])
|
if (a[RTA_OIF])
|
||||||
memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
|
memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
|
||||||
else
|
|
||||||
oif = ~0;
|
|
||||||
|
|
||||||
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.name);
|
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.name);
|
||||||
|
|
||||||
@ -782,7 +788,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|||||||
src = KRT_SRC_ALIEN;
|
src = KRT_SRC_ALIEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
net = net_get(p->p.table, dst, i->rtm_dst_len);
|
net *net = net_get(p->p.table, dst, i->rtm_dst_len);
|
||||||
|
|
||||||
rta ra = {
|
rta ra = {
|
||||||
.proto = &p->p,
|
.proto = &p->p,
|
||||||
@ -871,15 +877,49 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = rte_get_temp(&ra);
|
rte *e = rte_get_temp(&ra);
|
||||||
e->net = net;
|
e->net = net;
|
||||||
e->u.krt.src = src;
|
e->u.krt.src = src;
|
||||||
e->u.krt.proto = i->rtm_protocol;
|
e->u.krt.proto = i->rtm_protocol;
|
||||||
e->u.krt.type = i->rtm_type;
|
e->u.krt.type = i->rtm_type;
|
||||||
|
|
||||||
if (a[RTA_PRIORITY])
|
if (a[RTA_PRIORITY])
|
||||||
memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
|
memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
|
||||||
else
|
else
|
||||||
e->u.krt.metric = 0;
|
e->u.krt.metric = 0;
|
||||||
|
|
||||||
|
if (a[RTA_PREFSRC])
|
||||||
|
{
|
||||||
|
ip_addr ps;
|
||||||
|
memcpy(&ps, RTA_DATA(a[RTA_PREFSRC]), sizeof(ps));
|
||||||
|
ipa_ntoh(ps);
|
||||||
|
|
||||||
|
ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
|
||||||
|
ea->next = ra.eattrs;
|
||||||
|
ra.eattrs = ea;
|
||||||
|
ea->flags = EALF_SORTED;
|
||||||
|
ea->count = 1;
|
||||||
|
ea->attrs[0].id = EA_KRT_PREFSRC;
|
||||||
|
ea->attrs[0].flags = 0;
|
||||||
|
ea->attrs[0].type = EAF_TYPE_IP_ADDRESS;
|
||||||
|
ea->attrs[0].u.ptr = alloca(sizeof(struct adata) + sizeof(ps));
|
||||||
|
ea->attrs[0].u.ptr->length = sizeof(ps);
|
||||||
|
memcpy(ea->attrs[0].u.ptr->data, &ps, sizeof(ps));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a[RTA_FLOW])
|
||||||
|
{
|
||||||
|
ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
|
||||||
|
ea->next = ra.eattrs;
|
||||||
|
ra.eattrs = ea;
|
||||||
|
ea->flags = EALF_SORTED;
|
||||||
|
ea->count = 1;
|
||||||
|
ea->attrs[0].id = EA_KRT_REALM;
|
||||||
|
ea->attrs[0].flags = 0;
|
||||||
|
ea->attrs[0].type = EAF_TYPE_INT;
|
||||||
|
memcpy(&ea->attrs[0].u.data, RTA_DATA(a[RTA_FLOW]), 4);
|
||||||
|
}
|
||||||
|
|
||||||
if (scan)
|
if (scan)
|
||||||
krt_got_route(p, e);
|
krt_got_route(p, e);
|
||||||
else
|
else
|
||||||
|
@ -890,6 +890,7 @@ krt_init(struct proto_config *c)
|
|||||||
p->p.accept_ra_types = RA_OPTIMAL;
|
p->p.accept_ra_types = RA_OPTIMAL;
|
||||||
p->p.import_control = krt_import_control;
|
p->p.import_control = krt_import_control;
|
||||||
p->p.rt_notify = krt_notify;
|
p->p.rt_notify = krt_notify;
|
||||||
|
|
||||||
return &p->p;
|
return &p->p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,15 +908,35 @@ krt_reconfigure(struct proto *p, struct proto_config *new)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
krt_get_attr(eattr * a, byte * buf, int buflen UNUSED)
|
||||||
|
{
|
||||||
|
switch (a->id)
|
||||||
|
{
|
||||||
|
case EA_KRT_PREFSRC:
|
||||||
|
bsprintf(buf, "prefsrc");
|
||||||
|
return GA_NAME;
|
||||||
|
case EA_KRT_REALM:
|
||||||
|
bsprintf(buf, "realm");
|
||||||
|
return GA_NAME;
|
||||||
|
default:
|
||||||
|
return GA_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct protocol proto_unix_kernel = {
|
struct protocol proto_unix_kernel = {
|
||||||
name: "Kernel",
|
name: "Kernel",
|
||||||
template: "kernel%d",
|
template: "kernel%d",
|
||||||
|
attr_class: EAP_KRT,
|
||||||
preconfig: krt_preconfig,
|
preconfig: krt_preconfig,
|
||||||
postconfig: krt_postconfig,
|
postconfig: krt_postconfig,
|
||||||
init: krt_init,
|
init: krt_init,
|
||||||
start: krt_start,
|
start: krt_start,
|
||||||
shutdown: krt_shutdown,
|
shutdown: krt_shutdown,
|
||||||
reconfigure: krt_reconfigure,
|
reconfigure: krt_reconfigure,
|
||||||
|
get_attr: krt_get_attr,
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
dump: krt_dump,
|
dump: krt_dump,
|
||||||
dump_attrs: krt_dump_attrs,
|
dump_attrs: krt_dump_attrs,
|
||||||
|
@ -30,6 +30,10 @@ struct kif_proto;
|
|||||||
|
|
||||||
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
|
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
|
||||||
|
|
||||||
|
|
||||||
|
#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0)
|
||||||
|
#define EA_KRT_REALM EA_CODE(EAP_KRT, 1)
|
||||||
|
|
||||||
/* Whenever we recognize our own routes, we allow learing of foreign routes */
|
/* Whenever we recognize our own routes, we allow learing of foreign routes */
|
||||||
|
|
||||||
#ifdef CONFIG_SELF_CONSCIOUS
|
#ifdef CONFIG_SELF_CONSCIOUS
|
||||||
|
Loading…
Reference in New Issue
Block a user