summaryrefslogtreecommitdiff
path: root/proto/static
diff options
context:
space:
mode:
Diffstat (limited to 'proto/static')
-rw-r--r--proto/static/config.Y8
-rw-r--r--proto/static/static.c43
-rw-r--r--proto/static/static.h1
3 files changed, 43 insertions, 9 deletions
diff --git a/proto/static/config.Y b/proto/static/config.Y
index c8862171..215681e8 100644
--- a/proto/static/config.Y
+++ b/proto/static/config.Y
@@ -107,15 +107,21 @@ stat_nexthops:
| stat_nexthops stat_nexthop
;
+stat_mpls:
+ /* empty */
+ | MPLS expr { this_srt->mpls_label = $2; if ($2 >= MPLS_MAX_LABEL) cf_error("MPLS label must be less than 2^20"); }
+ ;
+
stat_route0: ROUTE net_any {
this_srt = cfg_allocz(sizeof(struct static_route));
add_tail(&STATIC_CFG->routes, &this_srt->n);
this_srt->net = $2;
+ this_srt->mpls_label = (uint) -1;
this_srt_cmds = NULL;
this_srt_last_cmd = NULL;
this_srt->mp_next = NULL;
this_snh = NULL;
- }
+ } stat_mpls
;
stat_route:
diff --git a/proto/static/static.c b/proto/static/static.c
index 35aa91c7..0e80ad64 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -103,16 +103,37 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
{
struct mpls_channel *mc = (void *) p->p.mpls_channel;
- ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
- *ea = (ea_list) { .flags = EALF_SORTED, .count = 1 };
+ ea_list *ea = alloca(sizeof(ea_list) + 2 * sizeof(eattr));
+ *ea = (ea_list) { .flags = EALF_SORTED };
ea->next = a->eattrs;
a->eattrs = ea;
- ea->attrs[0] = (eattr) {
- .id = EA_MPLS_POLICY,
- .type = EAF_TYPE_INT,
- .u.data = mc->label_policy,
- };
+ if (r->mpls_label != (uint) -1)
+ {
+ ea->attrs[0] = (eattr) {
+ .id = EA_MPLS_LABEL,
+ .type = EAF_TYPE_INT,
+ .u.data = r->mpls_label,
+ };
+
+ ea->attrs[1] = (eattr) {
+ .id = EA_MPLS_POLICY,
+ .type = EAF_TYPE_INT,
+ .u.data = MPLS_POLICY_STATIC,
+ };
+
+ ea->count = 2;
+ }
+ else
+ {
+ ea->attrs[0] = (eattr) {
+ .id = EA_MPLS_POLICY,
+ .type = EAF_TYPE_INT,
+ .u.data = mc->label_policy,
+ };
+
+ ea->count = 1;
+ }
}
/* Already announced */
@@ -373,7 +394,7 @@ static inline int
static_same_rte(struct static_route *or, struct static_route *nr)
{
/* Note that i_same() requires arguments in (new, old) order */
- return static_same_dest(or, nr) && f_same(nr->cmds, or->cmds);
+ return (or->mpls_label == nr->mpls_label) && static_same_dest(or, nr) && f_same(nr->cmds, or->cmds);
}
static void
@@ -455,6 +476,7 @@ static_postconfig(struct proto_config *CF)
cf_error("Channel not specified");
struct channel_config *cc = proto_cf_main_channel(CF);
+ struct channel_config *mc = proto_cf_mpls_channel(CF);
if (!cf->igp_table_ip4)
cf->igp_table_ip4 = (cc->table->addr_type == NET_IP4) ?
@@ -465,9 +487,14 @@ static_postconfig(struct proto_config *CF)
cc->table : cf->c.global->def_tables[NET_IP6];
WALK_LIST(r, cf->routes)
+ {
if (r->net && (r->net->type != CF->net_type))
cf_error("Route %N incompatible with channel type", r->net);
+ if ((r->mpls_label != (uint) -1) && !mc)
+ cf_error("Route %N has MPLS label, but MPLS channel not specified", r->net);
+ }
+
static_index_routes(cf);
}
diff --git a/proto/static/static.h b/proto/static/static.h
index fc91f71c..a0a95a4b 100644
--- a/proto/static/static.h
+++ b/proto/static/static.h
@@ -48,6 +48,7 @@ struct static_route {
byte onlink; /* Gateway is onlink regardless of IP ranges */
byte weight; /* Multipath next hop weight */
byte use_bfd; /* Configured to use BFD */
+ uint mpls_label; /* Local MPLS label, -1 if unused */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
mpls_label_stack *mls; /* MPLS label stack; may be NULL */
};