diff options
Diffstat (limited to 'proto/static')
-rw-r--r-- | proto/static/config.Y | 8 | ||||
-rw-r--r-- | proto/static/static.c | 43 | ||||
-rw-r--r-- | proto/static/static.h | 1 |
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 */ }; |