aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2020-11-18 20:05:10 +0900
committerKazuki Yamaguchi <k@rhe.jp>2020-11-18 20:05:10 +0900
commitdfa2c106c9610875fa71828839b4e29f269a22f5 (patch)
tree99400a202f21c36c59635a7a20c50c8d2a03f377
parent51bf10ba1da1fd33df8cfdaaf44f5003707441a5 (diff)
parent023a0a63cbcbac2c5b056c317ad77240ed0fb7f6 (diff)
downloadbird-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.Y6
-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
-rw-r--r--nest/route.h10
-rw-r--r--nest/rt-attr.c35
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();