From: Ondrej Zajicek Date: Thu, 28 Mar 2024 15:22:23 +0000 (+0100) Subject: Merge commit '224a152c53f304881f8616a1c9255b467062a069' into thread-next X-Git-Tag: v3.0.0~261 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c195c7a0d50cd80656fc3cabc692a0464dd0cb2d;p=thirdparty%2Fbird.git Merge commit '224a152c53f304881f8616a1c9255b467062a069' into thread-next --- c195c7a0d50cd80656fc3cabc692a0464dd0cb2d diff --cc filter/config.Y index 45444eb2c,79786faa4..353e27ae4 --- a/filter/config.Y +++ b/filter/config.Y @@@ -941,30 -933,18 +941,18 @@@ term | term_dot_method - | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_PATH)); } - | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_CLIST)); } - | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_ECLIST)); } - | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, val_empty(T_LCLIST)); } + | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_PATH)); } + | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_CLIST)); } + | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_ECLIST)); } + | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_LCLIST)); } - | PREPEND '(' term ',' term ')' { - $$ = f_dispatch_method_x("prepend", $3->type, $3, $5); - cf_warn("prepend(x,y) function is deprecated, please use x.prepend(y)"); - } - | ADD '(' term ',' term ')' { - $$ = f_dispatch_method_x("add", $3->type, $3, $5); - cf_warn("add(x,y) function is deprecated, please use x.add(y)"); - } - | DELETE '(' term ',' term ')' { - $$ = f_dispatch_method_x("delete", $3->type, $3, $5); - cf_warn("delete(x,y) function is deprecated, please use x.delete(y)"); - } - | FILTER '(' term ',' term ')' { - $$ = f_dispatch_method_x("filter", $3->type, $3, $5); - cf_warn("filter(x,y) function is deprecated, please use x.filter(y)"); - } + | PREPEND '(' term ',' term ')' { $$ = f_dispatch_method_x("prepend", $3->type, $3, $5); } + | ADD '(' term ',' term ')' { $$ = f_dispatch_method_x("add", $3->type, $3, $5); } + | DELETE '(' term ',' term ')' { $$ = f_dispatch_method_x("delete", $3->type, $3, $5); } + | FILTER '(' term ',' term ')' { $$ = f_dispatch_method_x("filter", $3->type, $3, $5); } - | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT, $3); } - | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT, $5, $7, $3); } + | ROA_CHECK '(' rtable ')' { $$ = f_implicit_roa_check($3); } + | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK, $5, $7, $3); } | FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT, $3); } diff --cc filter/f-inst.c index dab6cdfb3,a3f441fcc..2a6ef6cf8 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@@ -859,32 -816,57 +859,37 @@@ } INST(FI_EA_GET, 1, 1) { /* Access to extended attributes */ - ACCESS_RTE; - ACCESS_EATTRS; ARG(1, T_ROUTE); DYNAMIC_ATTR; - RESULT_TYPE(da.f_type); + RESULT_TYPE(da->type); { - struct ea_list *eal = v1.val.rte ? v1.val.rte->attrs->eattrs : *fs->eattrs; - eattr *e = ea_find(eal, da.ea_code); + struct f_val empty; + const eattr *e = ea_find(v1.val.rte->attrs, da->id); - if (!e) { - RESULT_VAL(val_empty(da.f_type)); - break; - } + if (e) + { + ASSERT_DIE(e->type == da->type); - switch (e->type & EAF_TYPE_MASK) { - case EAF_TYPE_INT: - RESULT_(da.f_type, i, e->u.data); - break; - case EAF_TYPE_ROUTER_ID: - RESULT_(T_QUAD, i, e->u.data); - break; - case EAF_TYPE_OPAQUE: - if (da.f_type == T_ENUM_EMPTY) - RESULT_(T_ENUM_EMPTY, i, 0); - else - RESULT_(T_BYTESTRING, ad, e->u.ptr); - break; - case EAF_TYPE_IP_ADDRESS: - RESULT_(T_IP, ip, *((ip_addr *) e->u.ptr->data)); - break; - case EAF_TYPE_AS_PATH: - RESULT_(T_PATH, ad, e->u.ptr); - break; - case EAF_TYPE_BITFIELD: - RESULT_(T_BOOL, i, !!(e->u.data & (1u << da.bit))); - break; - case EAF_TYPE_INT_SET: - RESULT_(T_CLIST, ad, e->u.ptr); - break; - case EAF_TYPE_EC_SET: - RESULT_(T_ECLIST, ad, e->u.ptr); - break; - case EAF_TYPE_LC_SET: - RESULT_(T_LCLIST, ad, e->u.ptr); - break; - case EAF_TYPE_STRING: - RESULT_(T_STRING, s, (const char *) e->u.ptr->data); - break; - default: - bug("Unknown dynamic attribute type"); + switch (e->type) { + case T_IP: + RESULT_(T_IP, ip, *((const ip_addr *) e->u.ptr->data)); + break; ++ ++ case T_STRING: ++ RESULT_(T_STRING, s, (const char *) e->u.ptr->data); ++ break; ++ + default: + RESULT_VAL([[(struct f_val) { + .type = e->type, + .val.bval = e->u, + }]]); + } } + else if ((empty = f_get_empty(da->type)).type != T_VOID) + RESULT_VAL(empty); + else + RESULT_VOID; } } @@@ -900,30 -883,66 +905,35 @@@ FID_INTERPRET_BODY; { - struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); - - l->next = NULL; - l->flags = EALF_SORTED; - l->count = 1; - l->attrs[0].id = da.ea_code; - l->attrs[0].flags = da.flags; - l->attrs[0].type = da.type; - l->attrs[0].originated = 1; - l->attrs[0].fresh = 1; - l->attrs[0].undef = 0; - - switch (da.type) { - case EAF_TYPE_INT: - case EAF_TYPE_ROUTER_ID: - l->attrs[0].u.data = v1.val.i; - break; + struct eattr *a; - case EAF_TYPE_IP_ADDRESS:; - int len = sizeof(ip_addr); - struct adata *ad = lp_alloc(fs->pool, sizeof(struct adata) + len); - ad->length = len; - (* (ip_addr *) ad->data) = v1.val.ip; - l->attrs[0].u.ptr = ad; - break; + if (da->type >= EAF_TYPE__MAX) + bug("Unsupported attribute type"); - case EAF_TYPE_OPAQUE: - case EAF_TYPE_AS_PATH: - case EAF_TYPE_INT_SET: - case EAF_TYPE_EC_SET: - case EAF_TYPE_LC_SET: - l->attrs[0].u.ptr = v1.val.ad; + switch (da->type) { + case T_IFACE: + case T_OPAQUE: + runtime( "Setting opaque attribute is not allowed" ); break; - case EAF_TYPE_STRING:; - struct adata *d = lp_alloc_adata(fs->pool, strlen(v1.val.s) + 1); - memcpy(d->data, v1.val.s, d->length); - l->attrs[0].u.ptr = d; + case T_IP: + a = ea_set_attr(&fs->rte->attrs, + EA_LITERAL_STORE_ADATA(da, 0, &v1.val.ip, sizeof(ip_addr))); break; - case EAF_TYPE_BITFIELD: - { - /* First, we have to find the old value */ - eattr *e = ea_find(*fs->eattrs, da.ea_code); - u32 data = e ? e->u.data : 0; - - if (v1.val.i) - l->attrs[0].u.data = data | (1u << da.bit); - else - l->attrs[0].u.data = data & ~(1u << da.bit); - } ++ case T_STRING: ++ a = ea_set_attr(&fs->rte->attrs, ++ EA_LITERAL_STORE_ADATA(da, 0, &v1.val.s, strlen(v1.val.s) + 1)); + break; + default: - bug("Unknown dynamic attribute type"); + a = ea_set_attr(&fs->rte->attrs, + EA_LITERAL_GENERIC(da->id, da->type, 0, .u = v1.val.bval)); + break; } - f_rta_cow(fs); - l->next = *fs->eattrs; - *fs->eattrs = l; + a->originated = 1; + a->fresh = 1; } } diff --cc nest/rt-attr.c index e29ded29f,c8ef8e081..468b279d1 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@@ -1407,81 -953,78 +1407,84 @@@ ea_show(struct cli *c, const eattr *e byte buf[CLI_MSG_SIZE]; byte *pos = buf, *end = buf + sizeof(buf); - if (EA_IS_CUSTOM(e->id)) - { - const char *name = ea_custom_name(e->id); - if (name) - { - pos += bsprintf(pos, "%s", name); - status = GA_NAME; - } - else - pos += bsprintf(pos, "%02x.", EA_PROTO(e->id)); - } - else if (p = class_to_protocol[EA_PROTO(e->id)]) - { - pos += bsprintf(pos, "%s.", p->name); - if (p->get_attr) - status = p->get_attr(e, pos, end - pos); - pos += strlen(pos); - } - else if (EA_PROTO(e->id)) - pos += bsprintf(pos, "%02x.", EA_PROTO(e->id)); - else - status = get_generic_attr(e, &pos, end - pos); + ASSERT_DIE(e->id < ea_class_max); - if (status < GA_NAME) - pos += bsprintf(pos, "%02x", EA_ID(e->id)); - if (status < GA_FULL) - { - *pos++ = ':'; - *pos++ = ' '; + struct ea_class *cls = ea_class_global[e->id]; + ASSERT_DIE(cls); + + if (e->undef || cls->hidden) + return; + else if (cls->format) + cls->format(e, buf, end - buf); + else + switch (e->type) + { + case T_INT: + if ((cls == &ea_gen_igp_metric) && e->u.data >= IGP_METRIC_UNKNOWN) + return; - if (e->undef) - bsprintf(pos, "undefined"); - else - switch (e->type & EAF_TYPE_MASK) - { - case EAF_TYPE_INT: bsprintf(pos, "%u", e->u.data); break; - case EAF_TYPE_OPAQUE: + case T_OPAQUE: opaque_format(ad, pos, end - pos); break; - case EAF_TYPE_IP_ADDRESS: + case T_IP: bsprintf(pos, "%I", *(ip_addr *) ad->data); break; - case EAF_TYPE_ROUTER_ID: + case T_QUAD: bsprintf(pos, "%R", e->u.data); break; - case EAF_TYPE_AS_PATH: + case T_PATH: as_path_format(ad, pos, end - pos); break; - case EAF_TYPE_BITFIELD: - bsprintf(pos, "%08x", e->u.data); - break; - case EAF_TYPE_INT_SET: - ea_show_int_set(c, ad, 1, pos, buf, end); + case T_CLIST: + ea_show_int_set(c, cls->name, ad, 1, buf); return; - case EAF_TYPE_EC_SET: - ea_show_ec_set(c, ad, pos, buf, end); + case T_ECLIST: + ea_show_ec_set(c, cls->name, ad, buf); return; - case EAF_TYPE_LC_SET: - ea_show_lc_set(c, ad, pos, buf, end); + case T_LCLIST: + ea_show_lc_set(c, cls->name, ad, buf); return; - case EAF_TYPE_STRING: ++ case T_STRING: + bsnprintf(pos, end - pos, "%s", (const char *) ad->data); + break; + case T_NEXTHOP_LIST: + ea_show_nexthop_list(c, (struct nexthop_adata *) e->u.ptr); + return; + case T_HOSTENTRY: + ea_show_hostentry(ad, pos, end - pos); + break; default: bsprintf(pos, "", e->type); - } - } + } - if (status != GA_HIDDEN) - cli_printf(c, -1012, "\t%s", buf); + cli_printf(c, -1012, "\t%s: %s", cls->name, buf); +} + +static void +nexthop_dump(const struct adata *ad) +{ + struct nexthop_adata *nhad = (struct nexthop_adata *) ad; + + debug(":"); + + if (!NEXTHOP_IS_REACHABLE(nhad)) + { + const char *name = rta_dest_name(nhad->dest); + if (name) + debug(" %s", name); + else + debug(" D%d", nhad->dest); + } + else NEXTHOP_WALK(nh, nhad) + { + if (ipa_nonzero(nh->gw)) debug(" ->%I", nh->gw); + if (nh->labels) debug(" L %d", nh->label[0]); + for (int i=1; ilabels; i++) + debug("/%d", nh->label[i]); + debug(" [%s]", nh->iface ? nh->iface->name : "???"); + } } /**