summaryrefslogtreecommitdiff
path: root/sysdep/linux
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-03-19 16:23:42 +0100
committerMaria Matejka <mq@ucw.cz>2022-05-04 15:39:19 +0200
commit17f91f9e6e70f7e3f29502e854823c0d48571eaa (patch)
treefab70e2115ce8d4e070382368df3eff4f3f44b97 /sysdep/linux
parent165156beeb2926472bbceca3c103aacc3f81a8cc (diff)
Explicit definition structures of route attributes
Changes in internal API: * Every route attribute must be defined as struct ea_class somewhere. * Registration of route attributes known at startup must be done by ea_register_init() from protocol build functions. * Every attribute has now its symbol registered in a global symbol table defined as SYM_ATTRIBUTE * All attribute ID's are dynamically allocated. * Attribute value custom formatting hook is defined in the ea_class. * Attribute names are the same for display and filters, always prefixed by protocol name. Also added some unit testing code for filters with route attributes.
Diffstat (limited to 'sysdep/linux')
-rw-r--r--sysdep/linux/krt-sys.h32
-rw-r--r--sysdep/linux/netlink.Y45
-rw-r--r--sysdep/linux/netlink.c197
3 files changed, 133 insertions, 141 deletions
diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h
index 8897f889..aa90f6e4 100644
--- a/sysdep/linux/krt-sys.h
+++ b/sysdep/linux/krt-sys.h
@@ -34,38 +34,6 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
#define KRT_ALLOW_MERGE_PATHS 1
-#define EA_KRT_PREFSRC EA_CODE(PROTOCOL_KERNEL, 0x10)
-#define EA_KRT_REALM EA_CODE(PROTOCOL_KERNEL, 0x11)
-#define EA_KRT_SCOPE EA_CODE(PROTOCOL_KERNEL, 0x12)
-
-
-#define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */
-#define KRT_METRICS_OFFSET 0x20 /* Offset of EA_KRT_* vs RTAX_* */
-
-#define KRT_FEATURES_MAX 4
-
-/*
- * Following attributes are parts of RTA_METRICS kernel route attribute, their
- * ids must be consistent with their RTAX_* constants (+ KRT_METRICS_OFFSET)
- */
-#define EA_KRT_METRICS EA_CODE(PROTOCOL_KERNEL, 0x20) /* Dummy one */
-#define EA_KRT_LOCK EA_CODE(PROTOCOL_KERNEL, 0x21)
-#define EA_KRT_MTU EA_CODE(PROTOCOL_KERNEL, 0x22)
-#define EA_KRT_WINDOW EA_CODE(PROTOCOL_KERNEL, 0x23)
-#define EA_KRT_RTT EA_CODE(PROTOCOL_KERNEL, 0x24)
-#define EA_KRT_RTTVAR EA_CODE(PROTOCOL_KERNEL, 0x25)
-#define EA_KRT_SSTRESH EA_CODE(PROTOCOL_KERNEL, 0x26)
-#define EA_KRT_CWND EA_CODE(PROTOCOL_KERNEL, 0x27)
-#define EA_KRT_ADVMSS EA_CODE(PROTOCOL_KERNEL, 0x28)
-#define EA_KRT_REORDERING EA_CODE(PROTOCOL_KERNEL, 0x29)
-#define EA_KRT_HOPLIMIT EA_CODE(PROTOCOL_KERNEL, 0x2a)
-#define EA_KRT_INITCWND EA_CODE(PROTOCOL_KERNEL, 0x2b)
-#define EA_KRT_FEATURES EA_CODE(PROTOCOL_KERNEL, 0x2c)
-#define EA_KRT_RTO_MIN EA_CODE(PROTOCOL_KERNEL, 0x2d)
-#define EA_KRT_INITRWND EA_CODE(PROTOCOL_KERNEL, 0x2e)
-#define EA_KRT_QUICKACK EA_CODE(PROTOCOL_KERNEL, 0x2f)
-
-
struct krt_params {
u32 table_id; /* Kernel table ID we sync with */
u32 metric; /* Kernel metric used for all routes */
diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y
index f31b88c7..17e17789 100644
--- a/sysdep/linux/netlink.Y
+++ b/sysdep/linux/netlink.Y
@@ -28,39 +28,22 @@ kern_sys_item:
| NETLINK RX BUFFER expr { THIS_KRT->sys.netlink_rx_buffer = $4; }
;
-dynamic_attr: KRT_PREFSRC { $$ = f_new_dynamic_attr(T_IP, EA_KRT_PREFSRC); } ;
-dynamic_attr: KRT_REALM { $$ = f_new_dynamic_attr(T_INT, EA_KRT_REALM); } ;
-dynamic_attr: KRT_SCOPE { $$ = f_new_dynamic_attr(T_INT, EA_KRT_SCOPE); } ;
-
-dynamic_attr: KRT_MTU { $$ = f_new_dynamic_attr(T_INT, EA_KRT_MTU); } ;
-dynamic_attr: KRT_WINDOW { $$ = f_new_dynamic_attr(T_INT, EA_KRT_WINDOW); } ;
-dynamic_attr: KRT_RTT { $$ = f_new_dynamic_attr(T_INT, EA_KRT_RTT); } ;
-dynamic_attr: KRT_RTTVAR { $$ = f_new_dynamic_attr(T_INT, EA_KRT_RTTVAR); } ;
-dynamic_attr: KRT_SSTRESH { $$ = f_new_dynamic_attr(T_INT, EA_KRT_SSTRESH); } ;
-dynamic_attr: KRT_CWND { $$ = f_new_dynamic_attr(T_INT, EA_KRT_CWND); } ;
-dynamic_attr: KRT_ADVMSS { $$ = f_new_dynamic_attr(T_INT, EA_KRT_ADVMSS); } ;
-dynamic_attr: KRT_REORDERING { $$ = f_new_dynamic_attr(T_INT, EA_KRT_REORDERING); } ;
-dynamic_attr: KRT_HOPLIMIT { $$ = f_new_dynamic_attr(T_INT, EA_KRT_HOPLIMIT); } ;
-dynamic_attr: KRT_INITCWND { $$ = f_new_dynamic_attr(T_INT, EA_KRT_INITCWND); } ;
-dynamic_attr: KRT_RTO_MIN { $$ = f_new_dynamic_attr(T_INT, EA_KRT_RTO_MIN); } ;
-dynamic_attr: KRT_INITRWND { $$ = f_new_dynamic_attr(T_INT, EA_KRT_INITRWND); } ;
-dynamic_attr: KRT_QUICKACK { $$ = f_new_dynamic_attr(T_INT, EA_KRT_QUICKACK); } ;
-
/* Bits of EA_KRT_LOCK, based on RTAX_* constants */
-attr_bit: KRT_LOCK_MTU { $$ = f_new_dynamic_attr_bit(2, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_WINDOW { $$ = f_new_dynamic_attr_bit(3, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_RTT { $$ = f_new_dynamic_attr_bit(4, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_RTTVAR { $$ = f_new_dynamic_attr_bit(5, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_SSTRESH { $$ = f_new_dynamic_attr_bit(6, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_CWND { $$ = f_new_dynamic_attr_bit(7, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_ADVMSS { $$ = f_new_dynamic_attr_bit(8, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_REORDERING { $$ = f_new_dynamic_attr_bit(9, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_HOPLIMIT { $$ = f_new_dynamic_attr_bit(10, EA_KRT_LOCK); } ;
-attr_bit: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr_bit(13, EA_KRT_LOCK); } ;
-
-attr_bit: KRT_FEATURE_ECN { $$ = f_new_dynamic_attr_bit(0, EA_KRT_FEATURES); } ;
-attr_bit: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr_bit(3, EA_KRT_FEATURES); } ;
+attr_bit: KRT_LOCK_MTU { $$ = f_new_dynamic_attr_bit(2, "krt_lock"); } ;
+attr_bit: KRT_LOCK_WINDOW { $$ = f_new_dynamic_attr_bit(3, "krt_lock"); } ;
+attr_bit: KRT_LOCK_RTT { $$ = f_new_dynamic_attr_bit(4, "krt_lock"); } ;
+attr_bit: KRT_LOCK_RTTVAR { $$ = f_new_dynamic_attr_bit(5, "krt_lock"); } ;
+attr_bit: KRT_LOCK_SSTRESH { $$ = f_new_dynamic_attr_bit(6, "krt_lock"); } ;
+attr_bit: KRT_LOCK_CWND { $$ = f_new_dynamic_attr_bit(7, "krt_lock"); } ;
+attr_bit: KRT_LOCK_ADVMSS { $$ = f_new_dynamic_attr_bit(8, "krt_lock"); } ;
+attr_bit: KRT_LOCK_REORDERING { $$ = f_new_dynamic_attr_bit(9, "krt_lock"); } ;
+attr_bit: KRT_LOCK_HOPLIMIT { $$ = f_new_dynamic_attr_bit(10, "krt_lock"); } ;
+attr_bit: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr_bit(13, "krt_lock"); } ;
+
+/* Bits of EA_KRT_FEATURES */
+attr_bit: KRT_FEATURE_ECN { $$ = f_new_dynamic_attr_bit(0, "krt_features"); } ;
+attr_bit: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr_bit(3, "krt_features"); } ;
CF_CODE
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 81e02b4c..23d41b56 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -26,6 +26,7 @@
#include "lib/socket.h"
#include "lib/string.h"
#include "lib/hash.h"
+#include "lib/macro.h"
#include "conf/conf.h"
#include <asm/types.h>
@@ -122,6 +123,101 @@ struct nl_parse_state
};
/*
+ * Netlink eattr definitions
+ */
+
+#define KRT_METRICS_MAX ARRAY_SIZE(ea_krt_metrics)
+#define KRT_FEATURES_MAX 4
+
+static void krt_bitfield_format(const eattr *e, byte *buf, uint buflen);
+
+static struct ea_class
+ ea_krt_prefsrc = {
+ .name = "krt_prefsrc",
+ .type = T_IP,
+ },
+ ea_krt_realm = {
+ .name = "krt_realm",
+ .type = T_INT,
+ },
+ ea_krt_scope = {
+ .name = "krt_scope",
+ .type = T_INT,
+ };
+
+static struct ea_class ea_krt_metrics[] = {
+ [RTAX_LOCK] = {
+ .name = "krt_lock",
+ .type = T_INT,
+ .format = krt_bitfield_format,
+ },
+ [RTAX_FEATURES] = {
+ .name = "krt_features",
+ .type = T_INT,
+ .format = krt_bitfield_format,
+ },
+#define KRT_METRIC_INT(_rtax, _name) [_rtax] = { .name = _name, .type = T_INT }
+ KRT_METRIC_INT(RTAX_MTU, "krt_mtu"),
+ KRT_METRIC_INT(RTAX_WINDOW, "krt_window"),
+ KRT_METRIC_INT(RTAX_RTT, "krt_rtt"),
+ KRT_METRIC_INT(RTAX_RTTVAR, "krt_rttvar"),
+ KRT_METRIC_INT(RTAX_SSTHRESH, "krt_sstresh"),
+ KRT_METRIC_INT(RTAX_CWND, "krt_cwnd"),
+ KRT_METRIC_INT(RTAX_ADVMSS, "krt_advmss"),
+ KRT_METRIC_INT(RTAX_REORDERING, "krt_reordering"),
+ KRT_METRIC_INT(RTAX_HOPLIMIT, "krt_hoplimit"),
+ KRT_METRIC_INT(RTAX_INITCWND, "krt_initcwnd"),
+ KRT_METRIC_INT(RTAX_RTO_MIN, "krt_rto_min"),
+ KRT_METRIC_INT(RTAX_INITRWND, "krt_initrwnd"),
+ KRT_METRIC_INT(RTAX_QUICKACK, "krt_quickack"),
+#undef KRT_METRIC_INT
+};
+
+static const char *krt_metrics_names[KRT_METRICS_MAX] = {
+ NULL, "lock", "mtu", "window", "rtt", "rttvar", "sstresh", "cwnd", "advmss",
+ "reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack"
+};
+
+static const char *krt_features_names[KRT_FEATURES_MAX] = {
+ "ecn", NULL, NULL, "allfrag"
+};
+
+static void
+krt_bitfield_format(const eattr *a, byte *buf, uint buflen)
+{
+ if (a->id == ea_krt_metrics[RTAX_LOCK].id)
+ ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX);
+ else if (a->id == ea_krt_metrics[RTAX_FEATURES].id)
+ ea_format_bitfield(a, buf, buflen, krt_features_names, 0, KRT_FEATURES_MAX);
+}
+
+static void
+nl_ea_register(void)
+{
+ EA_REGISTER_ALL(
+ &ea_krt_prefsrc,
+ &ea_krt_realm,
+ &ea_krt_scope
+ );
+
+ for (uint i = 0; i < KRT_METRICS_MAX; i++)
+ {
+ if (!ea_krt_metrics[i].name)
+ ea_krt_metrics[i] = (struct ea_class) {
+ .name = mb_sprintf(&root_pool, "krt_metric_%d", i),
+ .type = T_INT,
+ };
+
+ ea_register_init(&ea_krt_metrics[i]);
+ }
+
+ for (uint i = 1; i < KRT_METRICS_MAX; i++)
+ ASSERT_DIE(ea_krt_metrics[i].id == ea_krt_metrics[0].id + i);
+}
+
+
+
+/*
* Synchronous Netlink interface
*/
@@ -734,7 +830,7 @@ static void
nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct nexthop *nh, int af, ea_list *eattrs)
{
struct rtattr *a = nl_open_attr(h, bufsize, RTA_MULTIPATH);
- eattr *flow = ea_find(eattrs, EA_KRT_REALM);
+ eattr *flow = ea_find(eattrs, &ea_krt_realm);
for (; nh; nh = nh->next)
{
@@ -1399,7 +1495,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
priority = 0;
else if (KRT_CF->sys.metric)
priority = KRT_CF->sys.metric;
- else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, EA_KRT_METRIC)))
+ else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, &ea_krt_metric)))
priority = ea->u.data;
if (priority)
@@ -1412,15 +1508,15 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
/* Default scope is LINK for device routes, UNIVERSE otherwise */
if (p->af == AF_MPLS)
r->r.rtm_scope = RT_SCOPE_UNIVERSE;
- else if (ea = ea_find(eattrs, EA_KRT_SCOPE))
+ else if (ea = ea_find(eattrs, &ea_krt_scope))
r->r.rtm_scope = ea->u.data;
else
r->r.rtm_scope = (dest == RTD_UNICAST && ipa_zero(nh->gw)) ? 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, rsize, RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
- if (ea = ea_find(eattrs, EA_KRT_REALM))
+ if (ea = ea_find(eattrs, &ea_krt_realm))
nl_add_attr_u32(&r->h, rsize, RTA_FLOW, ea->u.data);
@@ -1428,9 +1524,9 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
metrics[0] = 0;
struct ea_walk_state ews = { .eattrs = eattrs };
- while (ea = ea_walk(&ews, EA_KRT_METRICS, KRT_METRICS_MAX))
+ while (ea = ea_walk(&ews, ea_krt_metrics[0].id, KRT_METRICS_MAX))
{
- int id = ea->id - EA_KRT_METRICS;
+ int id = ea->id - ea_krt_metrics[0].id;
metrics[0] |= 1 << id;
metrics[id] = ea->u.data;
}
@@ -1581,21 +1677,15 @@ nl_announce_route(struct nl_parse_state *s)
rte *e = rte_get_temp(s->attrs, s->proto->p.main_source);
e->net = s->net;
- EA_LOCAL_LIST(2) ea0 = {
+ EA_LOCAL_LIST(2) ea = {
.l = { .count = 2, .next = e->attrs->eattrs },
- .a[0] = (eattr) {
- .id = EA_KRT_SOURCE,
- .type = T_INT,
- .u.data = s->krt_proto,
- },
- .a[1] = (eattr) {
- .id = EA_KRT_METRIC,
- .type = T_INT,
- .u.data = s->krt_metric,
+ .a = {
+ EA_LITERAL_EMBEDDED(&ea_krt_source, 0, s->krt_proto),
+ EA_LITERAL_EMBEDDED(&ea_krt_metric, 0, s->krt_metric),
},
};
- e->attrs->eattrs = &ea0.l;
+ e->attrs->eattrs = &ea.l;
if (s->scan)
krt_got_route(s->proto, e, s->krt_src);
@@ -1867,20 +1957,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if (i->rtm_scope != def_scope)
ea_set_attr(&ra->eattrs,
- EA_LITERAL_EMBEDDED(EA_KRT_SCOPE, T_INT, 0, i->rtm_scope));
+ EA_LITERAL_EMBEDDED(&ea_krt_scope, 0, i->rtm_scope));
if (a[RTA_PREFSRC])
- {
- ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]);
+ {
+ ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]);
- ea_set_attr(&ra->eattrs,
- EA_LITERAL_STORE_ADATA(EA_KRT_PREFSRC, T_IP, 0, &ps, sizeof(ps)));
- }
+ ea_set_attr(&ra->eattrs,
+ EA_LITERAL_STORE_ADATA(&ea_krt_prefsrc, 0, &ps, sizeof(ps)));
+ }
/* Can be set per-route or per-nexthop */
if (s->rta_flow)
ea_set_attr(&ra->eattrs,
- EA_LITERAL_EMBEDDED(EA_KRT_REALM, T_INT, 0, s->rta_flow));
+ EA_LITERAL_EMBEDDED(&ea_krt_realm, 0, s->rta_flow));
if (a[RTA_METRICS])
{
@@ -1891,11 +1981,10 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
return;
}
- for (int t = 1; t < KRT_METRICS_MAX; t++)
+ for (uint t = 1; t < KRT_METRICS_MAX; t++)
if (metrics[0] & (1 << t))
ea_set_attr(&ra->eattrs,
- EA_LITERAL_EMBEDDED(EA_CODE(PROTOCOL_KERNEL, KRT_METRICS_OFFSET + t),
- T_INT, 0, metrics[t]));
+ EA_LITERAL_EMBEDDED(&ea_krt_metrics[t], 0, metrics[t]));
}
/*
@@ -2133,6 +2222,8 @@ krt_sys_io_init(void)
{
nl_linpool = lp_new_default(krt_pool);
HASH_INIT(nl_table_map, krt_pool, 6);
+
+ nl_ea_register();
}
int
@@ -2186,56 +2277,6 @@ krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
d->sys.metric = s->sys.metric;
}
-static const char *krt_metrics_names[KRT_METRICS_MAX] = {
- NULL, "lock", "mtu", "window", "rtt", "rttvar", "sstresh", "cwnd", "advmss",
- "reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack"
-};
-
-static const char *krt_features_names[KRT_FEATURES_MAX] = {
- "ecn", NULL, NULL, "allfrag"
-};
-
-int
-krt_sys_get_attr(const 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;
-
- case EA_KRT_SCOPE:
- bsprintf(buf, "scope");
- return GA_NAME;
-
- case EA_KRT_LOCK:
- buf += bsprintf(buf, "lock:");
- ea_format_bitfield(a, buf, buflen, krt_metrics_names, 2, KRT_METRICS_MAX);
- return GA_FULL;
-
- case EA_KRT_FEATURES:
- buf += bsprintf(buf, "features:");
- ea_format_bitfield(a, buf, buflen, krt_features_names, 0, KRT_FEATURES_MAX);
- return GA_FULL;
-
- default:;
- int id = (int)EA_ID(a->id) - KRT_METRICS_OFFSET;
- if (id > 0 && id < KRT_METRICS_MAX)
- {
- bsprintf(buf, "%s", krt_metrics_names[id]);
- return GA_NAME;
- }
-
- return GA_UNKNOWN;
- }
-}
-
-
-
void
kif_sys_start(struct kif_proto *p UNUSED)
{