From 3be732e6ab860adc364e3c8cac188d7c8f269689 Mon Sep 17 00:00:00 2001
From: Pim van Pelt <pim@ipng.nl>
Date: Sat, 9 Jul 2022 10:14:15 +0000
Subject: [PATCH] Remove the workaround for endianness in VPP; Remove the
 --disable-lcp flag. Catch connect exceptions for VPPStats and VPP API

---
 agentx/agent.py   |  8 +++++++-
 vpp-snmp-agent.py | 44 +++++++++++++++++++++++++++++---------------
 vppapi.py         | 25 ++-----------------------
 3 files changed, 38 insertions(+), 39 deletions(-)

diff --git a/agentx/agent.py b/agentx/agent.py
index 92612be..184dab0 100644
--- a/agentx/agent.py
+++ b/agentx/agent.py
@@ -33,8 +33,12 @@ class Agent(object):
 
     def _update(self):
         ds = self.update()
+        if not ds:
+            return False
+
         self._net.update(ds._data)
         self._lastupdate = time.time()
+        return True
 
     def run(self):
         self.logger.info('Calling setup')
@@ -51,7 +55,9 @@ class Agent(object):
               self._net.start(self._oid_list)
 
             if time.time() - self._lastupdate > self._update_period:
-                self._update()
+                if not self._update():
+                    self.logger.warning('Update failed, last successful update was %s' % self._lastupdate)
+                    time.sleep(1)
 
             try:
                 self._net.run()
diff --git a/vpp-snmp-agent.py b/vpp-snmp-agent.py
index 2b7640e..3ac61e5 100755
--- a/vpp-snmp-agent.py
+++ b/vpp-snmp-agent.py
@@ -47,13 +47,19 @@ class MyAgent(agentx.Agent):
             except:
                 self.logger.error("Couldn't read config from %s" % args.config)
 
-        self.logger.info("Connecting to VPP Stats Segment")
-        vppstat = VPPStats(socketname='/run/vpp/stats.sock', timeout=2)
-        vppstat.connect()
+        try:
+            self.logger.info("Connecting to VPP Stats Segment")
+            vppstat = VPPStats(socketname='/run/vpp/stats.sock', timeout=2)
+            vppstat.connect()
+        except:
+            self.logger.error("Could not connect to VPPStats segment")
+            return False
 
-        vpp = VPPApi(clientname='vpp-snmp-agent')
-        if not vpp.connect():
-            logger.error("Can't connect to VPP API, bailing")
+        try:
+            vpp = VPPApi(clientname='vpp-snmp-agent')
+            vpp.connect()
+        except:
+            self.logger.error("Could not connect to VPP API")
             return False
 
         self.register('1.3.6.1.2.1.2.2.1')
@@ -64,15 +70,23 @@ class MyAgent(agentx.Agent):
 
     def update(self):
         global vppstat, vpp, args
-        vppstat.connect()
-        vpp.connect()
+
+        try:
+            vppstat.connect()
+        except:
+            self.logger.error("Could not connect to VPPStats segment")
+            return False
+
+        try:
+            vpp.connect()
+        except:
+            self.logger.error("Could not connect to VPP API")
+            return False
 
         ds = agentx.DataSet()
         ifaces = vpp.get_ifaces()
-        if args.disable_lcp:
-            lcp = []
-        else:
-            lcp = vpp.get_lcp()
+        lcp = vpp.get_lcp()
+
         num_ifaces=len(ifaces)
         num_vppstat=len(vppstat['/if/names'])
         num_lcp=len(lcp)
@@ -80,7 +94,8 @@ class MyAgent(agentx.Agent):
         self.logger.debug("Retrieved Interfaces: vppapi=%d vppstats=%d lcp=%d" % (num_ifaces, num_vppstat, num_lcp))
 
         if num_ifaces != num_vppstat:
-            self.logger.warning("Interfaces count mismatch: vppapi=%d vppstats=%d" % (num_ifaces, num_vppstat))
+            self.logger.error("Interfaces count mismatch: vppapi=%d vppstats=%d" % (num_ifaces, num_vppstat))
+            return False
 
         for i in range(len(vppstat['/if/names'])):
             ifname = vppstat['/if/names'][i]
@@ -91,7 +106,7 @@ class MyAgent(agentx.Agent):
             ifName=ifname
             ifAlias=None
             try:
-                if (not args.disable_lcp) and self.config and ifname.startswith('tap'):
+                if self.config and ifname.startswith('tap'):
                     host_sw_if_index = ifaces[ifname].sw_if_index
                     lip = get_lcp_by_host_sw_if_index(lcp, host_sw_if_index)
                     if lip:
@@ -215,7 +230,6 @@ def main():
     global args
 
     parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
-    parser.add_argument('-disable-lcp', dest='disable_lcp', action='store_true', help="""Disable Linux Control Plane integration""")
     parser.add_argument('-a', dest='address', default="localhost:705", type=str, help="""Location of the SNMPd agent (unix-path or host:port), default localhost:705""")
     parser.add_argument('-p', dest='period', type=int, default=30, help="""Period to poll VPP, default 30 (seconds)""")
     parser.add_argument('-c', dest='config', type=str, help="""Optional YAML configuration file, default empty""")
diff --git a/vppapi.py b/vppapi.py
index 02546af..b2a43ee 100644
--- a/vppapi.py
+++ b/vppapi.py
@@ -88,7 +88,6 @@ class VPPApi():
         if not self.connected:
             return ret
 
-
         try:
             lcp_list = self.vpp.api.lcp_itf_pair_get()
         except Exception as e:
@@ -97,30 +96,10 @@ class VPPApi():
             self.connected = False
             return ret
 
-        if not lcp_list or not lcp_list[1]:
+        if not lcp_list:
             logger.error("Can't get LCP list")
             return ret
 
-        ## TODO(pim) - fix upstream, the indexes are in network byte order and
-        ## the message is messed up. This hack allows for both little endian and
-        ## big endian responses, and will be removed once VPP's LinuxCP is updated
-        ## and rolled out to AS8298
         for lcp in lcp_list[1]:
-            if lcp.phy_sw_if_index > 65535 or lcp.host_sw_if_index > 65535 or lcp.vif_index > 65535:
-                i = {
-                  'phy_sw_if_index': socket.ntohl(lcp.phy_sw_if_index),
-                  'host_sw_if_index': socket.ntohl(lcp.host_sw_if_index),
-                  'vif_index': socket.ntohl(lcp.vif_index),
-                  'host_if_name': lcp.host_if_name,
-                  'namespace': lcp.namespace
-                  }
-            else:
-                i = {
-                  'phy_sw_if_index': lcp.phy_sw_if_index,
-                  'host_sw_if_index': lcp.host_sw_if_index,
-                  'vif_index': lcp.vif_index,
-                  'host_if_name': lcp.host_if_name,
-                  'namespace': lcp.namespace
-                  }
-            ret[lcp.host_if_name] = i
+            ret[lcp.host_if_name] = lcp
         return ret