From: Maria Matejka Date: Tue, 31 Oct 2023 09:20:22 +0000 (+0100) Subject: Merge commit 'f0187d713c36e841fe8bab350e84f5257a74981a' into thread-next X-Git-Tag: v3.0.0~366 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d18a68cef7790607fcf814caeaf618ca0e682f41;p=thirdparty%2Fbird.git Merge commit 'f0187d713c36e841fe8bab350e84f5257a74981a' into thread-next --- d18a68cef7790607fcf814caeaf618ca0e682f41 diff --cc filter/data.c index c55cc7b0c,de745654a..ee10c5ac1 --- a/filter/data.c +++ b/filter/data.c @@@ -61,21 -58,23 +61,22 @@@ static const char * const f_type_str[] [T_RD] = "rd", [T_ROUTE] = "route", + [T_ROUTES_BLOCK] = "block of routes", + + [T_SET] = "set", + [T_PREFIX_SET] = "prefix set", }; +STATIC_ASSERT((1 << (8 * sizeof(btype))) == ARRAY_SIZE(f_type_str)); + const char * -f_type_name(enum f_type t) +f_type_name(btype t) { - if (t < ARRAY_SIZE(f_type_str)) - return f_type_str[t] ?: "?"; - - if ((t == T_SET) || (t == T_PREFIX_SET)) - return "set"; - - return "?"; + return f_type_str[t] ?: "?"; } -enum f_type -f_type_element_type(enum f_type t) +btype +f_type_element_type(btype t) { switch(t) { case T_PATH: return T_INT; @@@ -295,6 -304,15 +298,13 @@@ val_same(const struct f_val *v1, const return trie_same(v1->val.ti, v2->val.ti); case T_ROUTE: return rte_same(v1->val.rte, v2->val.rte); + case T_ROUTES_BLOCK: - for ( - rte *r1 = v1->val.rte, *r2 = v2->val.rte; - r1 || r2; - r1 = r1->next, r2 = r2->next - ) - if (!r1 || !r2 || !rte_same(r1, r2)) ++ if (v1->val.rte_block.len != v2->val.rte_block.len) ++ return 0; ++ for (uint i=0; i < v1->val.rte_block.len; i++) ++ if (!rte_same(v1->val.rte_block.rte[i], v2->val.rte_block.rte[i])) + return 0; + return 1; default: bug("Invalid type in val_same(): %x", v1->type); } @@@ -583,6 -601,19 +593,19 @@@ rte_format(const struct rte *rte, buffe buffer_puts(buf, "[No route]"); } + static void -rte_block_format(const struct rte *rte, buffer *buf) ++rte_block_format(const struct rte_block *block, buffer *buf) + { + buffer_print(buf, "Block of routes:"); + - for (int i = 0; rte; rte = rte->next, i++) ++ for (uint i = 0; i < block->len; i++) + { + buffer_print(buf, "%s%d: ", i ? "; " : " ", i); - rte_format(rte, buf); ++ rte_format(block->rte[i], buf); + } + } + + /* * val_format - format filter value */ @@@ -613,6 -644,7 +636,7 @@@ val_format(const struct f_val *v, buffe case T_LCLIST: lc_set_format(v->val.ad, -1, buf2, 1000); buffer_print(buf, "(lclist %s)", buf2); return; case T_PATH_MASK: pm_format(v->val.path_mask, buf); return; case T_ROUTE: rte_format(v->val.rte, buf); return; - case T_ROUTES_BLOCK: rte_block_format(v->val.rte, buf); return; ++ case T_ROUTES_BLOCK: rte_block_format(&v->val.rte_block, buf); return; default: buffer_print(buf, "[unknown type %x]", v->type); return; } } diff --cc filter/f-inst.c index b2b449cbe,42e38a4bf..4aa4c489d --- a/filter/f-inst.c +++ b/filter/f-inst.c @@@ -624,6 -617,34 +624,19 @@@ METHOD_CONSTRUCTOR("!for_next"); } + INST(FI_ROUTES_BLOCK_FOR_NEXT, 3, 0) { + NEVER_CONSTANT; + ARG(1, T_ROUTES_BLOCK); + - /* Loop auxiliary variable is initialized to T_VOID. - * In the first run, we initialize the auxiliary variable - * to the routes block supplied. It changes its type - * to T_ROUTES_BLOCK and therefore won't be run again. */ - if (v2.type == T_VOID) - v2 = v1; - - if (v2.val.rte) ++ if (v2.val.i < v1.val.rte_block.len) + { - /* There is some route to process, set it into the iterator variable. - * Its type has been already initialized by f_for_cycle(). */ - v3.val.rte = v2.val.rte; - v3.val.eattrs = v3.val.rte->attrs->eattrs; - - /* Prepare next route in the loop auxiliary variable */ - v2.val.rte = v2.val.rte->next; - - /* And execute the line */ ++ v3.val.rte = v1.val.rte_block.rte[v2.val.i++]; + LINE(2,0); + } + + METHOD_CONSTRUCTOR("!for_next"); + } + INST(FI_CONDITION, 1, 0) { ARG(1, T_BOOL); if (v1.val.i) diff --cc lib/type.h index 7260340ff,000000000..32f16382b mode 100644,000000..100644 --- a/lib/type.h +++ b/lib/type.h @@@ -1,117 -1,0 +1,122 @@@ +/* + * BIRD Internet Routing Daemon -- Internal Data Types + * + * (c) 2022 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _BIRD_TYPE_H_ +#define _BIRD_TYPE_H_ + +#include "lib/birdlib.h" +#include "lib/attrs.h" + +union bval { +#define BVAL_ITEMS \ + struct { \ + u32 data; /* Integer type inherited from eattrs */ \ + PADDING(data, 0, 4); /* Must be padded on 64-bits */ \ + }; \ + struct { \ + u32 i; /* Integer type inherited from filters */ \ + PADDING(i, 0, 4); /* Must be padded on 64-bits */ \ + }; \ + const struct adata *ptr; /* Generic attribute data inherited from eattrs */ \ + const struct adata *ad; /* Generic attribute data inherited from filters */ \ + + BVAL_ITEMS; +}; + +union bval_long { + union bval bval; /* For direct assignments */ + BVAL_ITEMS; /* For item-wise access */ + + u64 ec; + lcomm lc; + ip_addr ip; + const net_addr *net; + const char *s; + const struct adata *bs; + const struct f_tree *t; + const struct f_trie *ti; + const struct f_path_mask *path_mask; + struct f_path_mask_item pmi; + struct rte *rte; ++ struct rte_block { ++ struct rte **rte; ++ uint len; ++ } rte_block; +}; + + +/* Internal types */ +enum btype { +/* Nothing. Simply nothing. */ + T_VOID = 0, + T_NONE = 0xff, + +/* Something but inaccessible. */ + T_OPAQUE = 0x02, /* Opaque byte string (not filterable) */ + T_IFACE = 0x0c, /* Pointer to an interface (inside adata) */ ++ T_ROUTES_BLOCK = 0x68, /* Block of route pointers */ + T_ROUTE = 0x6a, /* One route pointer */ + T_NEXTHOP_LIST = 0x6c, /* The whole nexthop block */ + T_HOSTENTRY = 0x6e, /* Hostentry with possible MPLS labels */ + +/* Types shared with eattrs */ + T_INT = 0x01, /* 32-bit unsigned integer number */ + T_IP = 0x04, /* IP address */ + T_QUAD = 0x05, /* Router ID (IPv4 address) */ + T_PATH = 0x06, /* BGP AS path (encoding per RFC 1771:4.3) */ + T_CLIST = 0x0a, /* Set of u32's (e.g., a community list) */ + T_ECLIST = 0x0e, /* Set of pairs of u32's - ext. community list */ + T_LCLIST = 0x08, /* Set of triplets of u32's - large community list */ + + T_ENUM_BGP_ORIGIN = 0x11, /* BGP Origin enum */ + T_ENUM_RA_PREFERENCE = 0x13, /* RA Preference enum */ + T_ENUM_FLOWSPEC_VALID = 0x15, /* Flowspec validation result */ + +#define EAF_TYPE__MAX 0x1f +#define EAF_EMBEDDED 0x01 /* Data stored in eattr.u.data (part of type spec) */ + /* Otherwise, attribute data is adata */ + +/* Other user visible types which fit in int */ + T_BOOL = 0xa0, + T_PAIR = 0xa4, /* Notice that pair is stored as integer: first << 16 | second */ + +/* Put enumerational types in 0x20..0x3f range */ + T_ENUM_LO = 0x10, + T_ENUM_HI = 0x3f, + + T_ENUM_RTS = 0x31, + T_ENUM_SCOPE = 0x33, + T_ENUM_RTD = 0x37, + T_ENUM_ROA = 0x39, + T_ENUM_NETTYPE = 0x3b, + T_ENUM_AF = 0x3d, + +/* new enums go here */ + +#define T_ENUM T_ENUM_LO ... T_ENUM_HI + +/* Bigger ones */ + T_NET = 0xb0, + T_STRING = 0xb4, + T_PATH_MASK = 0xb8, /* mask for BGP path */ + T_EC = 0xbc, /* Extended community value, u64 */ + T_LC = 0xc0, /* Large community value, lcomm */ + T_RD = 0xc4, /* Route distinguisher for VPN addresses */ + T_PATH_MASK_ITEM = 0xc8, /* Path mask item for path mask constructors */ + T_BYTESTRING = 0xcc, + + T_SET = 0x80, + T_PREFIX_SET = 0x84, +} PACKED; + +typedef enum btype btype; + +STATIC_ASSERT(sizeof(btype) == sizeof(byte)); + + +#endif