From: Ondrej Zajicek Date: Thu, 28 Mar 2024 16:46:04 +0000 (+0100) Subject: Merge commit '225943eaea3cdd634dce8fd84547baf1bc363640' into thread-next X-Git-Tag: v3.0.0~260 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d548665de8e8f41359250d01e563b2c67931b66d;p=thirdparty%2Fbird.git Merge commit '225943eaea3cdd634dce8fd84547baf1bc363640' into thread-next --- d548665de8e8f41359250d01e563b2c67931b66d diff --cc sysdep/linux/netlink.c index 1145cf732,fb54de391..06a6ea72c --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@@ -43,101 -42,6 +43,106 @@@ struct nl_parse_stat u32 rta_flow; }; +/* + * 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, + }, ++ [RTAX_CC_ALGO] = { ++ .name = "krt_congctl", ++ .type = T_STRING, ++ }, +#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" ++ "reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack", ++ "congctl" +}; + +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 */ @@@ -929,8 -831,10 +943,8 @@@ err return NULL; } -STATIC_ASSERT(EA_KRT_METRICS + RTAX_CC_ALGO == EA_KRT_CONGCTL); - static void - nl_add_metrics(struct nlmsghdr *h, uint bufsize, u32 *metrics, int max) + nl_add_metrics(struct nlmsghdr *h, uint bufsize, u32 *metrics, const char *cc_algo, int max) { struct rtattr *a = nl_open_attr(h, bufsize, RTA_METRICS); int t; @@@ -1498,17 -1414,21 +1530,21 @@@ nl_send_route(struct krt_proto *p, cons 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; + + if (id == RTAX_CC_ALGO) + cc_algo = ea->u.ptr->data; + else + metrics[id] = ea->u.data; } if (metrics[0]) - nl_add_metrics(&r->h, rsize, metrics, KRT_METRICS_MAX); + nl_add_metrics(&r->h, rsize, metrics, cc_algo, KRT_METRICS_MAX); - switch (a->dest) + switch (dest) { case RTD_UNICAST: r->r.rtm_type = RTN_UNICAST; @@@ -1868,27 -1828,54 +1904,31 @@@ nl_parse_route(struct nl_parse_state *s if (a[RTA_METRICS]) { u32 metrics[KRT_METRICS_MAX]; - if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0) + const char *cc_algo = NULL; - ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + KRT_METRICS_MAX * sizeof(eattr)); - int t, n = 0; + + if (nl_parse_metrics(a[RTA_METRICS], metrics, &cc_algo, ARRAY_SIZE(metrics)) < 0) { - log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr); + log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net); return; } - for (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, - EA_LITERAL_EMBEDDED(&ea_krt_metrics[t], 0, metrics[t])); + if (t == RTAX_CC_ALGO) - { - struct adata *ad = lp_alloc_adata(s->pool, strlen(cc_algo)); - memcpy(ad->data, cc_algo, ad->length); - - ea->attrs[n++] = (eattr) { - .id = EA_KRT_CONGCTL, - .type = EAF_TYPE_STRING, - .u.ptr = ad, - }; - } ++ ea_set_attr(&ra, EA_LITERAL_STORE_ADATA(&ea_krt_metrics[t], 0, cc_algo, strlen(cc_algo))); + else - { - ea->attrs[n++] = (eattr) { - .id = EA_KRT_METRICS + t, - .type = EAF_TYPE_INT, /* FIXME: Some are EAF_TYPE_BITFIELD */ - .u.data = metrics[t], - }; - } - - if (n > 0) - { - ea->next = ra->eattrs; - ea->flags = EALF_SORTED; - ea->count = n; - ra->eattrs = ea; - } ++ ea_set_attr(&ra, EA_LITERAL_EMBEDDED(&ea_krt_metrics[t], 0, metrics[t])); } - rte *e = rte_get_temp(ra, p->p.main_source); - e->net = net; + rte e0 = { + .net = net, + .attrs = ra, + }; if (s->scan) - krt_got_route(p, e, krt_src); + krt_got_route(p, &e0, krt_src); else - krt_got_route_async(p, e, new, krt_src); + krt_got_route_async(p, &e0, new, krt_src); lp_flush(s->pool); }