diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2019-12-01 17:55:53 +0000 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2020-06-28 16:20:35 +0900 |
commit | f9e03c539932be03ee77cc02776c6474d2dd9008 (patch) | |
tree | badd64e289148a81d57cda6a6b8bd6a1131700a6 | |
parent | 82937b465b3a50bdcb00eff0b7aa6acb3fc21772 (diff) | |
download | bird-f9e03c539932be03ee77cc02776c6474d2dd9008.tar.gz |
Filter: Allow manually setting MPLS label
Heh
-rw-r--r-- | filter/config.Y | 5 | ||||
-rw-r--r-- | filter/data.c | 10 | ||||
-rw-r--r-- | filter/data.h | 2 | ||||
-rw-r--r-- | filter/f-inst.c | 17 |
4 files changed, 34 insertions, 0 deletions
diff --git a/filter/config.Y b/filter/config.Y index 557a951f..e8860675 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -288,6 +288,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH, EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, + ATTACH_MLS, BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT) %nonassoc THEN @@ -905,6 +906,10 @@ cmd: | dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_FILTER, $1, $5 ); } | BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); } | BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); } + | ATTACH_MLS '(' label_stack ')' ';' { $$ = f_new_inst(FI_ATTACH_MLS, + f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_MLS, .val.mls = $3, })); } + | ATTACH_MLS '(' ')' ';' { $$ = f_new_inst(FI_ATTACH_MLS, + f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_MLS, .val.mls = cfg_allocz(sizeof(mpls_label_stack)), })); } ; get_cf_position: diff --git a/filter/data.c b/filter/data.c index 40220255..23b0cd27 100644 --- a/filter/data.c +++ b/filter/data.c @@ -238,6 +238,14 @@ pm_same(const struct f_path_mask *m1, const struct f_path_mask *m2) return 1; } +static int +mpls_same(const mpls_label_stack *m1, const mpls_label_stack *m2) +{ + if (m1->len != m2->len) + return 0; + return !memcmp(m1->stack, m2->stack, m1->len * sizeof(u32)); +} + /** * val_same - compare two values * @v1: first value @@ -263,6 +271,8 @@ val_same(const struct f_val *v1, const struct f_val *v2) return pm_same(v1->val.path_mask, v2->val.path_mask); case T_PATH_MASK_ITEM: return pmi_same(&(v1->val.pmi), &(v2->val.pmi)); + case T_MLS: + return mpls_same(v1->val.mls, v2->val.mls); case T_PATH: case T_CLIST: case T_ECLIST: diff --git a/filter/data.h b/filter/data.h index 4ebce73b..dc56d88e 100644 --- a/filter/data.h +++ b/filter/data.h @@ -58,6 +58,7 @@ enum f_type { T_LCLIST = 0x29, /* Large community list */ T_RD = 0x2a, /* Route distinguisher for VPN addresses */ T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */ + T_MLS = 0x2c, T_SET = 0x80, T_PREFIX_SET = 0x81, @@ -78,6 +79,7 @@ struct f_val { const struct adata *ad; const struct f_path_mask *path_mask; struct f_path_mask_item pmi; + mpls_label_stack *mls; } val; }; diff --git a/filter/f-inst.c b/filter/f-inst.c index df908e26..dc375825 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -1210,6 +1210,23 @@ } + INST(FI_ATTACH_MLS, 1, 0) { /* attach_mls([stack]) */ + NEVER_CONSTANT; + ARG(1, T_MLS); + ACCESS_EATTRS; + ACCESS_RTE; + struct rta *rta = (*fs->rte)->attrs; + + const mpls_label_stack *mls = v1.val.mls; + for (struct nexthop *nh = &rta->nh; nh; nh = nh->next) { + nh->labels = mls ? mls->len : 0; + if (mls) + memcpy(&nh->label, mls->stack, mls->len * sizeof(u32)); + } + + RESULT_VOID; + } + INST(FI_FORMAT, 1, 0) { /* Format */ ARG_ANY(1); RESULT(T_STRING, s, val_format_str(fpool, &v1)); |