]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Static: Add syntax for static MPLS labels
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 22 Sep 2023 17:49:15 +0000 (19:49 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Wed, 4 Oct 2023 11:12:05 +0000 (13:12 +0200)
Instead of just using route attributes, static routes with
static MPLS labels can be defined just by e.g.:

  route 10.1.1.0/24 mpls 100 via 10.1.2.1 mpls 200;

nest/mpls.c
proto/static/config.Y
proto/static/static.c
proto/static/static.h

index ff76c05d9d21d7505dd5e7ff3cbddfe6f1017a80..03180913b7e06622aa16e4e7a36bf24dfc078587 100644 (file)
@@ -825,7 +825,9 @@ mpls_free_fec(struct mpls_fec_map *m, struct mpls_fec *fec)
 
   DBG("Free FEC %u\n", fec->label);
 
-  mpls_free_label(m->domain, m->handle, fec->label);
+  if (fec->policy != MPLS_POLICY_STATIC)
+    mpls_free_label(m->domain, m->handle, fec->label);
+
   HASH_REMOVE2(m->label_hash, LABEL, m->pool, fec);
 
   switch (fec->policy)
index c8862171a37222b157ac4575476d843783a32e89..215681e8b0895e3082021ae55c3b49692b804dd9 100644 (file)
@@ -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:
index 35aa91c70e13a67c95483b6709e6b2588bbbf6dc..0e80ad6466eee9396b016c37067789126e3d0ff8 100644 (file)
@@ -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);
 }
 
index fc91f71c6ead13241a62126234abb99bb1410b67..a0a95a4b7405b57a46c34edc23668c8ef8c24866 100644 (file)
@@ -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 */
 };