From eefa51f26b7a3f9d1c5befae862eb059a06eed8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Parisot?= <sparisot@free-mobile.fr>
Date: Mon, 9 Feb 2026 20:15:59 +0000
Subject: [PATCH 5/6] l3vpn: Make MPLS channel optional for SRv6 deployments

Guard all P->mpls_channel operations with NULL checks and remove
mandatory MPLS channel check in l3vpn_postconfig(). This allows
L3VPN to operate without an MPLS channel when using SRv6.
---
 proto/l3vpn/l3vpn.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/proto/l3vpn/l3vpn.c b/proto/l3vpn/l3vpn.c
index ece79d5..dbb1b80 100644
--- a/proto/l3vpn/l3vpn.c
+++ b/proto/l3vpn/l3vpn.c
@@ -227,8 +227,11 @@ l3vpn_rt_notify(struct proto *P, struct channel *c0, net *net, rte *new, rte *ol
 
     if (export)
     {
-      struct mpls_channel *mc = (void *) p->p.mpls_channel;
-      ea_set_attr_u32(&a->eattrs, tmp_linpool, EA_MPLS_POLICY, 0, EAF_TYPE_INT, mc->label_policy);
+      if (P->mpls_channel)
+      {
+        struct mpls_channel *mc = (void *) p->p.mpls_channel;
+        ea_set_attr_u32(&a->eattrs, tmp_linpool, EA_MPLS_POLICY, 0, EAF_TYPE_INT, mc->label_policy);
+      }
 
       struct adata *ad = l3vpn_export_targets(p, ea_get_adata(a0->eattrs, EA_BGP_EXT_COMMUNITY));
       ea_set_attr_ptr(&a->eattrs, tmp_linpool, EA_BGP_EXT_COMMUNITY, BAF_OPTIONAL | BAF_TRANSITIVE, EAF_TYPE_EC_SET, ad);
@@ -338,9 +341,6 @@ l3vpn_postconfig(struct proto_config *CF)
   if (!!proto_cf_find_channel(CF, NET_IP6) != !!proto_cf_find_channel(CF, NET_VPN6))
     cf_error("For IPv6 L3VPN, both IPv6 and VPNv6 channels must be specified");
 
-  if (!proto_cf_find_channel(CF, NET_MPLS))
-    cf_error("MPLS channel not specified");
-
   if (rd_zero(cf->rd))
     cf_error("Route distinguisher not specified");
 
@@ -389,10 +389,13 @@ l3vpn_start(struct proto *P)
   l3vpn_prepare_import_targets(p);
   l3vpn_prepare_export_targets(p);
 
-  proto_setup_mpls_map(P, RTS_L3VPN, 1);
+  if (P->mpls_channel)
+  {
+    proto_setup_mpls_map(P, RTS_L3VPN, 1);
 
-  if (P->vrf_set)
-    P->mpls_map->vrf_iface = P->vrf;
+    if (P->vrf_set)
+      P->mpls_map->vrf_iface = P->vrf;
+  }
 
   return PS_UP;
 }
@@ -402,7 +405,8 @@ l3vpn_shutdown(struct proto *P)
 {
   // struct l3vpn_proto *p = (void *) P;
 
-  proto_shutdown_mpls_map(P, 1);
+  if (P->mpls_channel)
+    proto_shutdown_mpls_map(P, 1);
 
   return PS_DOWN;
 }
@@ -430,7 +434,8 @@ 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, 1);
+  if (P->mpls_channel)
+    proto_setup_mpls_map(P, RTS_L3VPN, 1);
 
   if (import_changed)
   {
-- 
2.47.3

