]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
MPLS: FEC Map moved from protocol to MPLS channel
authorMaria Matejka <mq@ucw.cz>
Thu, 23 Nov 2023 23:05:51 +0000 (00:05 +0100)
committerMaria Matejka <mq@ucw.cz>
Mon, 8 Jan 2024 12:03:25 +0000 (13:03 +0100)
nest/mpls.c
nest/mpls.h
nest/proto.c
nest/protocol.h
nest/rt-table.c
proto/bgp/bgp.c
proto/l3vpn/l3vpn.c
proto/static/static.c

index 8c1c4517740113538d3dd5b5c4513e520d941bed..2cc3e04e96017ee2babe3b3cfb93254a1e0ed294 100644 (file)
@@ -565,6 +565,7 @@ mpls_channel_init(struct channel *C, struct channel_config *CC)
   c->domain = cc->domain->domain;
   c->range = cc->range->range;
   c->label_policy = cc->label_policy;
+  c->rts = cc->rts;
 }
 
 static int
@@ -575,6 +576,9 @@ mpls_channel_start(struct channel *C)
   mpls_lock_domain(c->domain);
   mpls_lock_range(c->range);
 
+  ASSERT_DIE(c->rts);
+  c->mpls_map = mpls_fec_map_new(C->proto->pool, C, c->rts);
+
   return 0;
 }
 
@@ -592,6 +596,9 @@ mpls_channel_cleanup(struct channel *C)
 {
   struct mpls_channel *c = (void *) C;
 
+  mpls_fec_map_free(c->mpls_map);
+  c->mpls_map = NULL;
+
   mpls_unlock_range(c->range);
   mpls_unlock_domain(c->domain);
 }
@@ -623,6 +630,8 @@ mpls_channel_reconfigure(struct channel *C, struct channel_config *CC, int *impo
     *import_changed = 1;
   }
 
+  mpls_fec_map_reconfigure(c->mpls_map, C);
+
   return 1;
 }
 
@@ -1141,8 +1150,10 @@ mpls_apply_fec(rte *r, struct mpls_fec *fec)
 
 
 int
-mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r)
+mpls_handle_rte(struct channel *c, const net_addr *n, rte *r)
 {
+  struct mpls_channel *mc = SKIP_BACK(struct mpls_channel, c, c->proto->mpls_channel);
+  struct mpls_fec_map *m = mc->mpls_map;
   struct mpls_fec *fec = NULL;
 
   /* Select FEC for route */
@@ -1214,13 +1225,13 @@ mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r)
 static inline struct mpls_fec_tmp_lock
 mpls_rte_get_fec_lock(const rte *r)
 {
-  struct mpls_fec_tmp_lock mt = {
-    .m = SKIP_BACK(struct proto, sources, r->src->owner)->mpls_map,
-  };
+  struct mpls_fec_tmp_lock mt = {};
 
-  if (!mt.m)
+  struct channel *c = SKIP_BACK(struct proto, sources, r->src->owner)->mpls_channel;
+  if (!c)
     return mt;
 
+  mt.m = SKIP_BACK(struct mpls_channel, c, c)->mpls_map;
   uint label = ea_get_int(r->attrs, &ea_gen_mpls_label, 0);
   if (label < 16)
     return mt;
index 60c382957919762228b9059c9871b0d80af63ff7..f6734001572b60efe0a059cb2fb710ceba026c03 100644 (file)
@@ -70,6 +70,7 @@ struct mpls_channel_config {
   struct mpls_range_config *range;
 
   uint label_policy;
+  uint rts;
 };
 
 struct mpls_channel {
@@ -79,12 +80,25 @@ struct mpls_channel {
   struct mpls_range *range;
 
   uint label_policy;
+  uint rts;
+
+  struct mpls_fec_map *mpls_map;       /* Maps protocol routes to FECs / labels */
 };
 
 
 void mpls_channel_postconfig(struct channel_config *CF);
 extern struct channel_class channel_mpls;
 
+static inline int
+proto_configure_mpls_channel(struct proto *p, struct proto_config *pc, uint rts)
+{
+  struct channel_config *cf = proto_cf_mpls_channel(pc);
+  if (cf)
+    SKIP_BACK(struct mpls_channel_config, c, cf)->rts = rts;
+
+  return proto_configure_channel(p, &p->mpls_channel, cf);
+}
+
 
 struct mpls_fec {
   u32 label;                           /* Label for FEC */
@@ -134,7 +148,7 @@ struct mpls_fec *mpls_get_fec_by_label(struct mpls_fec_map *m, u32 label);
 struct mpls_fec *mpls_get_fec_by_net(struct mpls_fec_map *m, const net_addr *net, u32 path_id);
 struct mpls_fec *mpls_get_fec_by_destination(struct mpls_fec_map *m, ea_list *dest);
 void mpls_free_fec(struct mpls_fec_map *x, struct mpls_fec *fec);
-int mpls_handle_rte(struct mpls_fec_map *m, const net_addr *n, rte *r);
+int mpls_handle_rte(struct channel *c, const net_addr *n, rte *r);
 void mpls_rte_preimport(rte *new, const rte *old);
 
 
index 6427afcd266ce369e259b99c1212a8a7597aee4f..c67a5a3a7f3dc2e6beeb4889958641d314bf0d0f 100644 (file)
@@ -1512,70 +1512,6 @@ proto_configure_channel(struct proto *p, struct channel **pc, struct channel_con
   return 1;
 }
 
-/**
- * proto_setup_mpls_map - automatically setup FEC map for protocol
- * @p: affected protocol
- * @rts: RTS_* value for generated MPLS routes
- * @hooks: whether to update rte_insert / rte_remove hooks
- *
- * Add, remove or reconfigure MPLS FEC map of the protocol @p, depends on
- * whether MPLS channel exists, and setup rte_insert / rte_remove hooks with
- * default MPLS handlers. It is a convenience function supposed to be called
- * from the protocol start and configure hooks, after reconfiguration of
- * channels. For shutdown, use proto_shutdown_mpls_map(). If caller uses its own
- * rte_insert / rte_remove hooks, it is possible to disable updating hooks and
- * doing that manually.
- */
-void
-proto_setup_mpls_map(struct proto *p, uint rts)
-{
-  struct mpls_fec_map *m = p->mpls_map;
-  struct channel *c = p->mpls_channel;
-
-  if (!m && c)
-  {
-    /*
-     * Note that when called from a protocol start hook, it is called before
-     * mpls_channel_start(). But FEC map locks MPLS domain internally so it does
-     * not depend on lock from MPLS channel.
-     */
-    p->mpls_map = mpls_fec_map_new(p->pool, c, rts);
-  }
-  else if (m && !c)
-  {
-    /*
-     * Note that for reconfiguration, it is called after the MPLS channel has
-     * been already removed. But removal of active MPLS channel would trigger
-     * protocol restart anyways.
-     */
-    mpls_fec_map_free(m);
-    p->mpls_map = NULL;
-  }
-  else if (m && c)
-  {
-    mpls_fec_map_reconfigure(m, c);
-  }
-}
-
-
-/**
- * proto_shutdown_mpls_map - automatically shutdown FEC map for protocol
- * @p: affected protocol
- * @hooks: whether to update rte_insert / rte_remove hooks
- *
- * Remove MPLS FEC map of the protocol @p during protocol shutdown.
- */
-void
-proto_shutdown_mpls_map(struct proto *p)
-{
-  struct mpls_fec_map *m = p->mpls_map;
-
-  if (!m)
-    return;
-
-  mpls_fec_map_free(m);
-  p->mpls_map = NULL;
-}
 
 static void
 proto_cleanup(struct proto *p)
index 4c983ffc903b3ab37a9d366cc95efeca8e84465c..aee2c08e46d8434fb091eded23f0d27ae04e1315 100644 (file)
@@ -34,7 +34,6 @@ struct channel;
 struct ea_list;
 struct eattr;
 struct symbol;
-struct mpls_fec_map;
 
 
 /*
@@ -160,7 +159,6 @@ struct proto {
   TLIST_LIST(proto_neigh) neighbors;   /* List of neighbor structures */
   struct iface_subscription iface_sub; /* Interface notification subscription */
   struct channel *mpls_channel;                /* MPLS channel, when used */
-  struct mpls_fec_map *mpls_map;       /* Maps protocol routes to FECs / labels */
 
   const char *name;                    /* Name of this instance (== cf->name) */
   u32 debug;                           /* Debugging flags */
@@ -687,8 +685,6 @@ struct channel *proto_find_channel_by_name(struct proto *p, const char *n);
 struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
 void proto_remove_channel(struct proto *p, struct channel *c);
 int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf);
-void proto_setup_mpls_map(struct proto *p, uint rts);
-void proto_shutdown_mpls_map(struct proto *p);
 
 void channel_set_state(struct channel *c, uint state);
 void channel_schedule_reload(struct channel *c, struct channel_import_request *cir);
index e1f6683ad29b899c757761143e6ab269719fc88c..29ee8bd38a9d7a45e6db586bfe873af6beb454fb 100644 (file)
@@ -1789,8 +1789,8 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
            new = NULL;
        }
 
-      if (new && c->proto->mpls_map)
-       if (mpls_handle_rte(c->proto->mpls_map, n, new) < 0)
+      if (new && c->proto->mpls_channel)
+       if (mpls_handle_rte(c->proto->mpls_channel, n, new) < 0)
          {
            channel_rte_trace_in(D_FILTERS, c, new, "invalid");
            stats->updates_invalid++;
index 24b952d9b070fbd112dcd5a3532a95097563ab96..c888460a0568c22781bcdfab12b5803a009e339f 100644 (file)
 #include "nest/iface.h"
 #include "nest/protocol.h"
 #include "nest/route.h"
+#include "nest/mpls.h"
 #include "nest/cli.h"
 #include "nest/locks.h"
 #include "conf/conf.h"
@@ -621,8 +622,6 @@ bgp_spawn(struct bgp_proto *pp, ip_addr remote_ip)
 void
 bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len)
 {
-  proto_shutdown_mpls_map(&p->p);
-
   proto_notify_state(&p->p, PS_STOP);
   p->uncork_ev->data = NULL;
   bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
@@ -1794,8 +1793,6 @@ bgp_start(struct proto *P)
   p->remote_id = 0;
   p->link_addr = IPA_NONE;
 
-  proto_setup_mpls_map(P, RTS_BGP);
-
   /* Lock all channels when in GR recovery mode */
   if (p->p.gr_recovery && p->cf->gr_mode)
   {
@@ -1966,7 +1963,7 @@ bgp_init(struct proto_config *CF)
     proto_add_channel(P, &cc->c);
 
   /* Add MPLS channel */
-  proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF));
+  proto_configure_mpls_channel(P, CF, RTS_BGP);
 
   return P;
 }
@@ -2392,15 +2389,12 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
   }
 
   /* Reconfigure MPLS channel */
-  same = proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)) && same;
+  same = proto_configure_mpls_channel(P, CF, RTS_BGP) && same;
 
   WALK_LIST_DELSAFE(C, C2, p->p.channels)
     if (C->stale)
       same = proto_configure_channel(P, &C, NULL) && same;
 
-  if (same)
-    proto_setup_mpls_map(P, RTS_BGP);
-
   if (same && (p->start_state > BSS_PREPARE))
     bgp_update_bfd(p, new->bfd);
 
index a3c5de9c6f35342c13f283f7a26d29246534c961..c899d202962327b2ef9ef28254a22759c275f2b1 100644 (file)
@@ -391,7 +391,8 @@ l3vpn_init(struct proto_config *CF)
   proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6));
   proto_configure_channel(P, &p->vpn4_channel, proto_cf_find_channel(CF, NET_VPN4));
   proto_configure_channel(P, &p->vpn6_channel, proto_cf_find_channel(CF, NET_VPN6));
-  proto_configure_channel(P, &P->mpls_channel, proto_cf_find_channel(CF, NET_MPLS));
+
+  proto_configure_mpls_channel(P, CF, RTS_L3VPN);
 
   P->rt_notify = l3vpn_rt_notify;
   P->preexport = l3vpn_preexport;
@@ -414,22 +415,20 @@ l3vpn_start(struct proto *P)
   l3vpn_prepare_import_targets(p);
   l3vpn_prepare_export_targets(p);
 
-  proto_setup_mpls_map(P, RTS_L3VPN);
-
-  P->mpls_map->vrf_iface = P->vrf;
+  SKIP_BACK(struct mpls_channel, c, P->mpls_channel)->mpls_map->vrf_iface = P->vrf;
 
   return PS_UP;
 }
 
+#if 0
 static int
-l3vpn_shutdown(struct proto *P)
+l3vpn_shutdown(struct proto *P UNUSED)
 {
   // struct l3vpn_proto *p = (void *) P;
 
-  proto_shutdown_mpls_map(P);
-
   return PS_DOWN;
 }
+#endif
 
 static int
 l3vpn_reconfigure(struct proto *P, struct proto_config *CF)
@@ -441,7 +440,7 @@ l3vpn_reconfigure(struct proto *P, struct proto_config *CF)
       !proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6)) ||
       !proto_configure_channel(P, &p->vpn4_channel, proto_cf_find_channel(CF, NET_VPN4)) ||
       !proto_configure_channel(P, &p->vpn6_channel, proto_cf_find_channel(CF, NET_VPN6)) ||
-      !proto_configure_channel(P, &P->mpls_channel, proto_cf_find_channel(CF, NET_MPLS)))
+      !proto_configure_mpls_channel(P, CF, RTS_L3VPN))
     return 0;
 
   if (p->rd != cf->rd)
@@ -454,8 +453,6 @@ l3vpn_reconfigure(struct proto *P, struct proto_config *CF)
   p->import_target = cf->import_target;
   p->export_target = cf->export_target;
 
-  proto_setup_mpls_map(P, RTS_L3VPN);
-
   if (import_changed)
   {
     TRACE(D_EVENTS, "Import target changed");
@@ -518,7 +515,7 @@ struct protocol proto_l3vpn = {
   .postconfig =                l3vpn_postconfig,
   .init =              l3vpn_init,
   .start =             l3vpn_start,
-  .shutdown =          l3vpn_shutdown,
+//  .shutdown =                l3vpn_shutdown,
   .reconfigure =       l3vpn_reconfigure,
   .copy_config =       l3vpn_copy_config,
 };
index 2024514f1ed3c6b36a246caf310a8c331214fba2..bdccabaf002ec40bb5d75f40505fd31bd75498af 100644 (file)
@@ -507,7 +507,7 @@ static_init(struct proto_config *CF)
 
   P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
 
-  proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF));
+  proto_configure_mpls_channel(P, CF, RTS_STATIC);
 
   P->iface_sub.neigh_notify = static_neigh_notify;
   P->reload_routes = static_reload_routes;
@@ -539,8 +539,6 @@ static_start(struct proto *P)
 
   BUFFER_INIT(p->marked, p->p.pool, 4);
 
-  proto_setup_mpls_map(P, RTS_STATIC);
-
   /* We have to go UP before routes could be installed */
   proto_notify_state(P, PS_UP);
 
@@ -558,8 +556,6 @@ static_shutdown(struct proto *P)
   struct static_config *cf = (void *) P->cf;
   struct static_route *r;
 
-  proto_shutdown_mpls_map(P);
-
   /* Just reset the flag, the routes will be flushed by the nest */
   WALK_LIST(r, cf->routes)
     static_reset_rte(p, r);
@@ -657,11 +653,9 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
     return 0;
 
   if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)) ||
-      !proto_configure_channel(P, &P->mpls_channel, proto_cf_mpls_channel(CF)))
+      !proto_configure_mpls_channel(P, CF, RTS_STATIC))
     return 0;
 
-  proto_setup_mpls_map(P, RTS_STATIC);
-
   p->p.cf = CF;
 
   /* Reset route lists in neighbor entries */