improved LLDP remote port search when collecting LLDP topology data
authorVictor Kirhenshtein <victor@netxms.org>
Thu, 28 Apr 2016 14:13:41 +0000 (17:13 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Thu, 28 Apr 2016 14:13:41 +0000 (17:13 +0300)
src/server/core/lldp.cpp
src/server/core/node.cpp
src/server/include/nms_objects.h
src/server/include/nms_topo.h

index 38ac2d8..a106260 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2015 Victor Kirhenshtein
+** Copyright (C) 2003-2016 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -39,12 +39,19 @@ static UINT32 PortLocalInfoHandler(UINT32 snmpVersion, SNMP_Variable *var, SNMP_
        newOid[oid->getLength() - 2] = 4;       // lldpLocPortDescr
        pRqPDU->bindVariable(new SNMP_Variable(newOid, oid->getLength()));
 
+   newOid[oid->getLength() - 2] = 2;   // lldpLocPortIdSubtype
+   pRqPDU->bindVariable(new SNMP_Variable(newOid, oid->getLength()));
+
        SNMP_PDU *pRespPDU = NULL;
    UINT32 rcc = transport->doRequest(pRqPDU, &pRespPDU, SnmpGetDefaultTimeout(), 3);
        delete pRqPDU;
        if (rcc == SNMP_ERR_SUCCESS)
    {
-               pRespPDU->getVariable(0)->getValueAsString(port->ifDescr, 192);
+          if (pRespPDU->getNumVariables() >= 2)
+          {
+             pRespPDU->getVariable(0)->getValueAsString(port->ifDescr, 192);
+             port->localIdSubtype = pRespPDU->getVariable(1)->getValueAsUInt();
+          }
                delete pRespPDU;
        }
        else
@@ -85,6 +92,19 @@ static Interface *FindRemoteInterface(Node *node, UINT32 idType, BYTE *id, size_
        TCHAR ifName[130];
        Interface *ifc;
 
+       // Try local LLDP port info first
+   if (node->getLldpLocalPortInfo(idType, id, idLen, &port))
+   {
+      if (node->isBridge())
+         ifc = node->findBridgePort(port.portNumber);
+      else
+         ifc = node->findInterfaceByIndex(port.portNumber);
+      if (ifc == NULL)  // unable to find interface by bridge port number or interface index, try description
+         ifc = node->findInterfaceByName(port.ifDescr);  /* TODO: find by cached ifName value */
+      if (ifc != NULL)
+         return ifc;
+   }
+
        switch(idType)
        {
                case 3: // MAC address
@@ -120,20 +140,7 @@ static Interface *FindRemoteInterface(Node *node, UINT32 idType, BYTE *id, size_
                        }
                        return ifc;
                case 7: // local identifier
-                       if (node->getLldpLocalPortInfo(id, idLen, &port))
-                       {
-            if (node->isBridge())
-               ifc = node->findBridgePort(port.portNumber);
-            else
-               ifc = node->findInterfaceByIndex(port.portNumber);
-            if (ifc == NULL)  // unable to find interface by bridge port number or interface index, try description
-               ifc = node->findInterfaceByName(port.ifDescr);  /* TODO: find by cached ifName value */
-                       }
-                       else
-                       {
-                               ifc = NULL;
-                       }
-                       return ifc;
+                       return NULL;   // already tried to find port using local info
                default:
                        return NULL;
        }
index 716d594..8439c47 100644 (file)
@@ -7104,11 +7104,12 @@ bool Node::isDataCollectionDisabled()
 /**
  * Get LLDP local port info by LLDP local ID
  *
+ * @param idType port ID type (value of lldpLocPortIdSubtype)
  * @param id port ID
  * @param idLen port ID length in bytes
  * @param buffer buffer for storing port information
  */
-bool Node::getLldpLocalPortInfo(BYTE *id, size_t idLen, LLDP_LOCAL_PORT_INFO *buffer)
+bool Node::getLldpLocalPortInfo(UINT32 idType, BYTE *id, size_t idLen, LLDP_LOCAL_PORT_INFO *buffer)
 {
        bool result = false;
        lockProperties();
@@ -7117,7 +7118,7 @@ bool Node::getLldpLocalPortInfo(BYTE *id, size_t idLen, LLDP_LOCAL_PORT_INFO *bu
                for(int i = 0; i < m_lldpLocalPortInfo->size(); i++)
                {
                        LLDP_LOCAL_PORT_INFO *port = m_lldpLocalPortInfo->get(i);
-                       if ((idLen == port->localIdLen) && !memcmp(id, port->localId, idLen))
+                       if ((idType == port->localIdSubtype) && (idLen == port->localIdLen) && !memcmp(id, port->localId, idLen))
                        {
             memcpy(buffer, port, sizeof(LLDP_LOCAL_PORT_INFO));
                                result = true;
index 3891600..b80e228 100644 (file)
@@ -1449,7 +1449,7 @@ public:
    bool getNextHop(const InetAddress& srcAddr, const InetAddress& destAddr, InetAddress *nextHop, UINT32 *ifIndex, bool *isVpn, TCHAR *name);
    bool getOutwardInterface(const InetAddress& destAddr, InetAddress *srcAddr, UINT32 *srcIfIndex);
        ComponentTree *getComponents();
-   bool getLldpLocalPortInfo(BYTE *id, size_t idLen, LLDP_LOCAL_PORT_INFO *port);
+   bool getLldpLocalPortInfo(UINT32 idType, BYTE *id, size_t idLen, LLDP_LOCAL_PORT_INFO *port);
 
        void setRecheckCapsFlag() { m_dwDynamicFlags |= NDF_RECHECK_CAPABILITIES; }
    void setDiscoveryPollTimeStamp();
index 70c8abe..265a5b8 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** NetXMS - Network Management System
-** Copyright (C) 2003-2013 Victor Kirhenshtein
+** Copyright (C) 2003-2016 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -34,6 +34,7 @@ class Interface;
 struct LLDP_LOCAL_PORT_INFO
 {
    UINT32 portNumber;
+   UINT32 localIdSubtype;
        BYTE localId[256];
        size_t localIdLen;
        TCHAR ifDescr[192];