KRT: Add krt_scope attribute
Add a new route attribute, krt_scope, to expose the Linux kernel route scope. Constants from /etc/iproute2/rt_scopes (prefixed by "ips_") are expected to be used with the attribute. Both import and export are supported. Also, the patch fixes device route export to the kernel, by setting link scope automatically.
This commit is contained in:
parent
292f7858e6
commit
6e75d0d27f
4 changed files with 38 additions and 8 deletions
|
@ -2443,6 +2443,15 @@ these attributes:
|
||||||
|
|
||||||
<tag>int <cf/krt_realm/</tag> (Linux)
|
<tag>int <cf/krt_realm/</tag> (Linux)
|
||||||
The realm of the route. Can be used for traffic classification.
|
The realm of the route. Can be used for traffic classification.
|
||||||
|
|
||||||
|
<tag>int <cf/krt_scope/</tag> (Linux IPv4)
|
||||||
|
The scope of the route. Valid values are 0-254, although Linux kernel
|
||||||
|
may reject some values depending on route type and nexthop. It is
|
||||||
|
supposed to represent `indirectness' of the route, where nexthops of
|
||||||
|
routes are resolved through routes with a higher scope, but in current
|
||||||
|
kernels anything below <it/link/ (253) is treated as <it/global/ (0).
|
||||||
|
When not present, global scope is implied for all routes except device
|
||||||
|
routes, where link scope is used by default.
|
||||||
</descrip>
|
</descrip>
|
||||||
|
|
||||||
<p>In Linux, there is also a plenty of obscure route attributes mostly focused
|
<p>In Linux, there is also a plenty of obscure route attributes mostly focused
|
||||||
|
|
|
@ -36,6 +36,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i) { return NULL; }
|
||||||
|
|
||||||
#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0x10)
|
#define EA_KRT_PREFSRC EA_CODE(EAP_KRT, 0x10)
|
||||||
#define EA_KRT_REALM EA_CODE(EAP_KRT, 0x11)
|
#define EA_KRT_REALM EA_CODE(EAP_KRT, 0x11)
|
||||||
|
#define EA_KRT_SCOPE EA_CODE(EAP_KRT, 0x12)
|
||||||
|
|
||||||
|
|
||||||
#define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */
|
#define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */
|
||||||
|
|
|
@ -10,7 +10,7 @@ CF_HDR
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_MTU, KRT_WINDOW,
|
CF_KEYWORDS(KERNEL, TABLE, METRIC, KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW,
|
||||||
KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
|
KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
|
||||||
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
|
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
|
||||||
KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
|
KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
|
||||||
|
@ -28,6 +28,7 @@ kern_sys_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_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_ADDTO(dynamic_attr, KRT_REALM { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REALM); })
|
||||||
|
CF_ADDTO(dynamic_attr, KRT_SCOPE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SCOPE); })
|
||||||
|
|
||||||
CF_ADDTO(dynamic_attr, KRT_MTU { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU); })
|
CF_ADDTO(dynamic_attr, KRT_MTU { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU); })
|
||||||
CF_ADDTO(dynamic_attr, KRT_WINDOW { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); })
|
CF_ADDTO(dynamic_attr, KRT_WINDOW { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); })
|
||||||
|
|
|
@ -899,7 +899,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
|
||||||
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_protocol = RTPROT_BIRD;
|
r.r.rtm_protocol = RTPROT_BIRD;
|
||||||
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
r.r.rtm_scope = RT_SCOPE_NOWHERE;
|
||||||
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -928,6 +928,12 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
|
||||||
if (op == NL_OP_DELETE)
|
if (op == NL_OP_DELETE)
|
||||||
goto dest;
|
goto dest;
|
||||||
|
|
||||||
|
/* Default scope is LINK for device routes, UNIVERSE otherwise */
|
||||||
|
if (ea = ea_find(eattrs, EA_KRT_SCOPE))
|
||||||
|
r.r.rtm_scope = ea->u.data;
|
||||||
|
else
|
||||||
|
r.r.rtm_scope = (dest == RTD_DEVICE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
|
||||||
|
|
||||||
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
|
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
|
||||||
|
|
||||||
|
@ -1135,6 +1141,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
u32 oif = ~0;
|
u32 oif = ~0;
|
||||||
u32 table;
|
u32 table;
|
||||||
u32 priority = 0;
|
u32 priority = 0;
|
||||||
|
u32 def_scope = RT_SCOPE_UNIVERSE;
|
||||||
int src;
|
int src;
|
||||||
|
|
||||||
if (!(i = nl_checkin(h, sizeof(*i))))
|
if (!(i = nl_checkin(h, sizeof(*i))))
|
||||||
|
@ -1157,7 +1164,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (a[RTA_DST])
|
if (a[RTA_DST])
|
||||||
{
|
{
|
||||||
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
|
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
|
||||||
|
@ -1195,11 +1201,6 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||||
SKIP("strange class/scope\n");
|
SKIP("strange class/scope\n");
|
||||||
|
|
||||||
// ignore rtm_scope, it is not a real scope
|
|
||||||
// if (i->rtm_scope != RT_SCOPE_UNIVERSE)
|
|
||||||
// SKIP("scope %u\n", i->rtm_scope);
|
|
||||||
|
|
||||||
|
|
||||||
switch (i->rtm_protocol)
|
switch (i->rtm_protocol)
|
||||||
{
|
{
|
||||||
case RTPROT_UNSPEC:
|
case RTPROT_UNSPEC:
|
||||||
|
@ -1286,6 +1287,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ra->dest = RTD_DEVICE;
|
ra->dest = RTD_DEVICE;
|
||||||
|
def_scope = RT_SCOPE_LINK;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1304,6 +1306,19 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i->rtm_scope != def_scope)
|
||||||
|
{
|
||||||
|
ea_list *ea = lp_alloc(s->pool, 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_SCOPE;
|
||||||
|
ea->attrs[0].flags = 0;
|
||||||
|
ea->attrs[0].type = EAF_TYPE_INT;
|
||||||
|
ea->attrs[0].u.data = i->rtm_scope;
|
||||||
|
}
|
||||||
|
|
||||||
if (a[RTA_PREFSRC])
|
if (a[RTA_PREFSRC])
|
||||||
{
|
{
|
||||||
ip_addr ps;
|
ip_addr ps;
|
||||||
|
@ -1633,6 +1648,10 @@ krt_sys_get_attr(eattr *a, byte *buf, int buflen UNUSED)
|
||||||
bsprintf(buf, "realm");
|
bsprintf(buf, "realm");
|
||||||
return GA_NAME;
|
return GA_NAME;
|
||||||
|
|
||||||
|
case EA_KRT_SCOPE:
|
||||||
|
bsprintf(buf, "scope");
|
||||||
|
return GA_NAME;
|
||||||
|
|
||||||
case EA_KRT_LOCK:
|
case EA_KRT_LOCK:
|
||||||
buf += bsprintf(buf, "lock:");
|
buf += bsprintf(buf, "lock:");
|
||||||
ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX);
|
ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX);
|
||||||
|
|
Loading…
Reference in a new issue