aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2019-12-01 17:55:53 +0000
committerKazuki Yamaguchi <k@rhe.jp>2020-06-28 16:20:35 +0900
commitf9e03c539932be03ee77cc02776c6474d2dd9008 (patch)
treebadd64e289148a81d57cda6a6b8bd6a1131700a6
parent82937b465b3a50bdcb00eff0b7aa6acb3fc21772 (diff)
downloadbird-f9e03c539932be03ee77cc02776c6474d2dd9008.tar.gz
Filter: Allow manually setting MPLS label
Heh
-rw-r--r--filter/config.Y5
-rw-r--r--filter/data.c10
-rw-r--r--filter/data.h2
-rw-r--r--filter/f-inst.c17
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));