diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2020-11-18 20:05:10 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2020-11-18 20:05:10 +0900 |
commit | dfa2c106c9610875fa71828839b4e29f269a22f5 (patch) | |
tree | 99400a202f21c36c59635a7a20c50c8d2a03f377 | |
parent | 51bf10ba1da1fd33df8cfdaaf44f5003707441a5 (diff) | |
parent | 023a0a63cbcbac2c5b056c317ad77240ed0fb7f6 (diff) | |
download | bird-dfa2c106c9610875fa71828839b4e29f269a22f5.tar.gz |
Merge branch 'ky/attach-mls' into master-2.0.7m
* ky/attach-mls:
Nest: Statically allocate space for MPLS labels
Conf: Allow expression in MPLS label stack
Filter: Allow manually setting MPLS label
-rw-r--r-- | conf/confbase.Y | 6 | ||||
-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 | ||||
-rw-r--r-- | nest/route.h | 10 | ||||
-rw-r--r-- | nest/rt-attr.c | 35 |
7 files changed, 50 insertions, 35 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y index f0343a93..7818b4de 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -278,7 +278,7 @@ net_roa6_: net_ip6_ MAX NUM AS NUM cf_error("Invalid max prefix length %u", $3); }; -net_mpls_: MPLS NUM +net_mpls_: MPLS expr { $$ = cfg_alloc(sizeof(net_addr_roa6)); net_fill_mpls($$, $2); @@ -342,7 +342,7 @@ net_or_ipa: } ; -label_stack_start: NUM +label_stack_start: expr { $$ = cfg_allocz(sizeof(mpls_label_stack)); $$->len = 1; @@ -351,7 +351,7 @@ label_stack_start: NUM label_stack: label_stack_start - | label_stack '/' NUM { + | label_stack '/' expr { if ($1->len >= MPLS_MAX_LABEL_STACK) cf_error("Too many labels in stack"); $1->stack[$1->len++] = $3; diff --git a/filter/config.Y b/filter/config.Y index 6a2caa94..51108a18 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 @@ -908,6 +909,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 7c33d2cb..da2bf6e3 100644 --- a/filter/data.c +++ b/filter/data.c @@ -248,6 +248,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 @@ -273,6 +281,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)); diff --git a/nest/route.h b/nest/route.h index 1b4f2866..3fa8f55a 100644 --- a/nest/route.h +++ b/nest/route.h @@ -397,7 +397,7 @@ struct nexthop { byte weight; byte labels_orig; /* Number of labels before hostentry was applied */ byte labels; /* Number of all labels */ - u32 label[0]; + u32 label[MPLS_MAX_LABEL_STACK]; }; #define RNF_ONLINK 0x1 /* Gateway is onlink regardless of IP ranges */ @@ -630,10 +630,10 @@ ea_set_attr_data(ea_list **to, struct linpool *pool, uint id, uint flags, uint t } -#define NEXTHOP_MAX_SIZE (sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK) +#define NEXTHOP_MAX_SIZE sizeof(struct nexthop) static inline size_t nexthop_size(const struct nexthop *nh) -{ return sizeof(struct nexthop) + sizeof(u32)*nh->labels; } +{ return sizeof(struct nexthop); } int nexthop__same(struct nexthop *x, struct nexthop *y); /* Compare multipath nexthops */ static inline int nexthop_same(struct nexthop *x, struct nexthop *y) { return (x == y) || nexthop__same(x, y); } @@ -645,8 +645,8 @@ void nexthop_insert(struct nexthop **n, struct nexthop *y); int nexthop_is_sorted(struct nexthop *x); void rta_init(void); -static inline size_t rta_size(const rta *a) { return sizeof(rta) + sizeof(u32)*a->nh.labels; } -#define RTA_MAX_SIZE (sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK) +static inline size_t rta_size(const rta *a) { return sizeof(rta); } +#define RTA_MAX_SIZE sizeof(rta) rta *rta_lookup(rta *); /* Get rta equivalent to this one, uc++ */ static inline int rta_is_cached(rta *r) { return r->aflags & RTAF_CACHED; } static inline rta *rta_clone(rta *r) { r->uc++; return r; } diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 28d956bc..e588f357 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -88,8 +88,8 @@ const char * rta_dest_names[RTD_MAX] = { pool *rta_pool; -static slab *rta_slab_[4]; -static slab *nexthop_slab_[4]; +static slab *rta_slab; +static slab *nexthop_slab; static slab *rte_src_slab; static struct idm src_ids; @@ -352,12 +352,6 @@ nexthop_is_sorted(struct nexthop *x) return 1; } -static inline slab * -nexthop_slab(struct nexthop *nh) -{ - return nexthop_slab_[MIN(nh->labels, 3)]; -} - static struct nexthop * nexthop_copy(struct nexthop *o) { @@ -366,7 +360,7 @@ nexthop_copy(struct nexthop *o) for (; o; o = o->next) { - struct nexthop *n = sl_alloc(nexthop_slab(o)); + struct nexthop *n = sl_alloc(nexthop_slab); n->gw = o->gw; n->iface = o->iface; n->next = NULL; @@ -392,7 +386,7 @@ nexthop_free(struct nexthop *o) while (o) { n = o->next; - sl_free(nexthop_slab(o), o); + sl_free(nexthop_slab, o); o = n; } } @@ -1125,16 +1119,10 @@ rta_same(rta *x, rta *y) ea_same(x->eattrs, y->eattrs)); } -static inline slab * -rta_slab(rta *a) -{ - return rta_slab_[a->nh.labels > 2 ? 3 : a->nh.labels]; -} - static rta * rta_copy(rta *o) { - rta *r = sl_alloc(rta_slab(o)); + rta *r = sl_alloc(rta_slab); memcpy(r, o, rta_size(o)); r->uc = 1; @@ -1229,7 +1217,7 @@ rta__free(rta *a) nexthop_free(a->nh.next); ea_free(a->eattrs); a->aflags = 0; /* Poison the entry */ - sl_free(rta_slab(a), a); + sl_free(rta_slab, a); } rta * @@ -1329,15 +1317,8 @@ rta_init(void) { rta_pool = rp_new(&root_pool, "Attributes"); - rta_slab_[0] = sl_new(rta_pool, sizeof(rta)); - rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)); - rta_slab_[2] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*2); - rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK); - - nexthop_slab_[0] = sl_new(rta_pool, sizeof(struct nexthop)); - nexthop_slab_[1] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)); - nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2); - nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK); + rta_slab = sl_new(rta_pool, sizeof(rta)); + nexthop_slab = sl_new(rta_pool, sizeof(struct nexthop)); rta_alloc_hash(); rte_src_init(); |