mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-03 07:31:54 +00:00
Filter: adding explicit route-block type
This is a split-commit of the neighboring aggregator branch with a bit improved lvalue handling, to have easier merge into v3.
This commit is contained in:
parent
de70474fed
commit
f0187d713c
@ -58,6 +58,7 @@ static const char * const f_type_str[] = {
|
|||||||
[T_RD] = "rd",
|
[T_RD] = "rd",
|
||||||
|
|
||||||
[T_ROUTE] = "route",
|
[T_ROUTE] = "route",
|
||||||
|
[T_ROUTES_BLOCK] = "block of routes",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@ -80,6 +81,7 @@ f_type_element_type(enum f_type t)
|
|||||||
case T_CLIST: return T_PAIR;
|
case T_CLIST: return T_PAIR;
|
||||||
case T_ECLIST: return T_EC;
|
case T_ECLIST: return T_EC;
|
||||||
case T_LCLIST: return T_LC;
|
case T_LCLIST: return T_LC;
|
||||||
|
case T_ROUTES_BLOCK: return T_ROUTE;
|
||||||
default: return T_VOID;
|
default: return T_VOID;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -209,6 +211,7 @@ val_compare(const struct f_val *v1, const struct f_val *v2)
|
|||||||
case T_STRING:
|
case T_STRING:
|
||||||
return strcmp(v1->val.s, v2->val.s);
|
return strcmp(v1->val.s, v2->val.s);
|
||||||
case T_ROUTE:
|
case T_ROUTE:
|
||||||
|
case T_ROUTES_BLOCK:
|
||||||
default:
|
default:
|
||||||
return F_CMP_ERROR;
|
return F_CMP_ERROR;
|
||||||
}
|
}
|
||||||
@ -301,6 +304,15 @@ val_same(const struct f_val *v1, const struct f_val *v2)
|
|||||||
return trie_same(v1->val.ti, v2->val.ti);
|
return trie_same(v1->val.ti, v2->val.ti);
|
||||||
case T_ROUTE:
|
case T_ROUTE:
|
||||||
return rte_same(v1->val.rte, v2->val.rte);
|
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))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
default:
|
default:
|
||||||
bug("Invalid type in val_same(): %x", v1->type);
|
bug("Invalid type in val_same(): %x", v1->type);
|
||||||
}
|
}
|
||||||
@ -589,6 +601,19 @@ rte_format(const struct rte *rte, buffer *buf)
|
|||||||
buffer_puts(buf, "[No route]");
|
buffer_puts(buf, "[No route]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rte_block_format(const struct rte *rte, buffer *buf)
|
||||||
|
{
|
||||||
|
buffer_print(buf, "Block of routes:");
|
||||||
|
|
||||||
|
for (int i = 0; rte; rte = rte->next, i++)
|
||||||
|
{
|
||||||
|
buffer_print(buf, "%s%d: ", i ? "; " : " ", i);
|
||||||
|
rte_format(rte, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* val_format - format filter value
|
* val_format - format filter value
|
||||||
*/
|
*/
|
||||||
@ -619,6 +644,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_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_PATH_MASK: pm_format(v->val.path_mask, buf); return;
|
||||||
case T_ROUTE: rte_format(v->val.rte, buf); return;
|
case T_ROUTE: rte_format(v->val.rte, buf); return;
|
||||||
|
case T_ROUTES_BLOCK: rte_block_format(v->val.rte, buf); return;
|
||||||
default: buffer_print(buf, "[unknown type %x]", v->type); return;
|
default: buffer_print(buf, "[unknown type %x]", v->type); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ enum f_type {
|
|||||||
T_BYTESTRING = 0x2c,
|
T_BYTESTRING = 0x2c,
|
||||||
|
|
||||||
T_ROUTE = 0x78,
|
T_ROUTE = 0x78,
|
||||||
|
T_ROUTES_BLOCK = 0x79,
|
||||||
T_SET = 0x80,
|
T_SET = 0x80,
|
||||||
T_PREFIX_SET = 0x81,
|
T_PREFIX_SET = 0x81,
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
@ -617,6 +617,34 @@
|
|||||||
METHOD_CONSTRUCTOR("!for_next");
|
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)
|
||||||
|
{
|
||||||
|
/* 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 */
|
||||||
|
LINE(2,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD_CONSTRUCTOR("!for_next");
|
||||||
|
}
|
||||||
|
|
||||||
INST(FI_CONDITION, 1, 0) {
|
INST(FI_CONDITION, 1, 0) {
|
||||||
ARG(1, T_BOOL);
|
ARG(1, T_BOOL);
|
||||||
if (v1.val.i)
|
if (v1.val.i)
|
||||||
|
Loading…
Reference in New Issue
Block a user