From 1c9590dccefba4ecf5699cafa0d4f461b2d563b8 Mon Sep 17 00:00:00 2001
From: Pim van Pelt <pim@ipng.nl>
Date: Sun, 11 Jun 2023 18:43:43 +0200
Subject: [PATCH] Set MPLS for loopback and interface. Allow for --novpp and
 VPP changes

---
 vppcfg/vpp/dumper.py     |  2 ++
 vppcfg/vpp/reconciler.py | 33 +++++++++++++++++++++++++++++++++
 vppcfg/vpp/vppapi.py     |  6 ++++++
 3 files changed, 41 insertions(+)

diff --git a/vppcfg/vpp/dumper.py b/vppcfg/vpp/dumper.py
index 15cd7b4..692735c 100644
--- a/vppcfg/vpp/dumper.py
+++ b/vppcfg/vpp/dumper.py
@@ -110,6 +110,8 @@ class Dumper(VPPApi):
                             loop["addresses"] = self.cache["interface_addresses"][
                                 iface.sw_if_index
                             ]
+                    if iface.sw_if_index in self.cache["interface_mpls"]:
+                        loop["mpls"] = self.cache["interface_mpls"][iface.sw_if_index]
                     config["loopbacks"][iface.interface_name] = loop
                 elif iface.interface_dev_type in [
                     "bond",
diff --git a/vppcfg/vpp/reconciler.py b/vppcfg/vpp/reconciler.py
index e3d0b7f..9e8b757 100644
--- a/vppcfg/vpp/reconciler.py
+++ b/vppcfg/vpp/reconciler.py
@@ -947,6 +947,9 @@ class Reconciler:
         if not self.__sync_phys():
             self.logger.warning("Could not sync PHYs in VPP")
             ret = False
+        if not self.__sync_mpls_state():
+            self.logger.warning("Could not sync interface MPLS state in VPP")
+            ret = False
         if not self.__sync_admin_state():
             self.logger.warning("Could not sync interface adminstate in VPP")
             ret = False
@@ -1291,6 +1294,36 @@ class Reconciler:
             ret = False
         return ret
 
+    def __sync_mpls_state(self):
+        """Synchronize the VPP Dataplane configuration for interface and loopback MPLS state"""
+        for ifname in interface.get_interfaces(self.cfg) + loopback.get_loopbacks(
+            self.cfg
+        ):
+            if ifname.startswith("loop"):
+                vpp_ifname, config_iface = loopback.get_by_name(self.cfg, ifname)
+            else:
+                vpp_ifname, config_iface = interface.get_by_name(self.cfg, ifname)
+
+            try:
+                config_mpls = config_iface["mpls"]
+            except KeyError:
+                config_mpls = False
+
+            vpp_mpls = False
+            if vpp_ifname in self.vpp.cache["interface_names"]:
+                sw_if_index = self.vpp.cache["interface_names"][vpp_ifname]
+                try:
+                    vpp_mpls = self.vpp.cache["interface_mpls"][sw_if_index]
+                except KeyError:
+                    pass
+            if vpp_mpls != config_mpls:
+                state = "disable"
+                if config_mpls:
+                    state = "enable"
+                cli = f"set interface mpls {vpp_ifname} {state}"
+                self.cli["sync"].append(cli)
+        return True
+
     def __sync_addresses(self):
         """Synchronize the VPP Dataplane configuration for interface addresses"""
         for ifname in interface.get_interfaces(self.cfg) + loopback.get_loopbacks(
diff --git a/vppcfg/vpp/vppapi.py b/vppcfg/vpp/vppapi.py
index 4b11a0e..c6a2be4 100644
--- a/vppcfg/vpp/vppapi.py
+++ b/vppcfg/vpp/vppapi.py
@@ -120,6 +120,7 @@ class VPPApi:
             "interfaces": {},
             "interface_addresses": {},
             "interface_acls": {},
+            "interface_mpls": {},
             "bondethernets": {},
             "bondethernet_members": {},
             "bridgedomains": {},
@@ -368,6 +369,11 @@ class VPPApi:
         for iface in api_response:
             self.cache["interface_acls"][iface.sw_if_index] = iface
 
+        self.logger.debug("Retrieving interface MPLS state")
+        api_response = self.vpp.api.mpls_interface_dump()
+        for iface in api_response:
+            self.cache["interface_mpls"][iface.sw_if_index] = True
+
         self.logger.debug("Retrieving bondethernets")
         api_response = self.vpp.api.sw_bond_interface_dump()
         for iface in api_response: