diff --git a/filter/data.c b/filter/data.c index c55cc7b0..ee10c5ac 100644 --- a/filter/data.c +++ b/filter/data.c @@ -61,6 +61,7 @@ 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", @@ -82,6 +83,7 @@ f_type_element_type(btype t) case T_CLIST: return T_PAIR; case T_ECLIST: return T_EC; case T_LCLIST: return T_LC; + case T_ROUTES_BLOCK: return T_ROUTE; default: return T_VOID; }; } @@ -203,6 +205,7 @@ val_compare(const struct f_val *v1, const struct f_val *v2) case T_STRING: return strcmp(v1->val.s, v2->val.s); case T_ROUTE: + case T_ROUTES_BLOCK: default: return F_CMP_ERROR; } @@ -295,6 +298,13 @@ val_same(const struct f_val *v1, const struct f_val *v2) 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: + 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 +593,19 @@ rte_format(const struct rte *rte, buffer *buf) buffer_puts(buf, "[No route]"); } +static void +rte_block_format(const struct rte_block *block, buffer *buf) +{ + buffer_print(buf, "Block of routes:"); + + for (uint i = 0; i < block->len; i++) + { + buffer_print(buf, "%s%d: ", i ? "; " : " ", i); + rte_format(block->rte[i], buf); + } +} + + /* * val_format - format filter value */ @@ -613,6 +636,7 @@ val_format(const struct f_val *v, buffer *buf) 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_block, buf); return; default: buffer_print(buf, "[unknown type %x]", v->type); return; } } diff --git a/filter/f-inst.c b/filter/f-inst.c index b2b449cb..4aa4c489 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -624,6 +624,19 @@ METHOD_CONSTRUCTOR("!for_next"); } + INST(FI_ROUTES_BLOCK_FOR_NEXT, 3, 0) { + NEVER_CONSTANT; + ARG(1, T_ROUTES_BLOCK); + + if (v2.val.i < v1.val.rte_block.len) + { + 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 --git a/lib/type.h b/lib/type.h index 7260340f..32f16382 100644 --- a/lib/type.h +++ b/lib/type.h @@ -43,6 +43,10 @@ union bval_long { 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; }; @@ -55,6 +59,7 @@ enum btype { /* 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 */