implemented SNMP target sync with agent for cached DCIs; GUID functions refactoring...
[public/netxms.git] / src / server / core / stp.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2013 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: stp.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24
25 /**
26 * STP port table walker's callback
27 */
28 static UINT32 STPPortListHandler(UINT32 snmpVersion, SNMP_Variable *var, SNMP_Transport *transport, void *arg)
29 {
30 int state = var->getValueAsInt();
31 if ((state != 2) && (state != 5))
32 return SNMP_ERR_SUCCESS; // port state not "blocked" or "forwarding"
33
34 Node *node = (Node *)((LinkLayerNeighbors *)arg)->getData();
35 UINT32 oid[64];
36 memcpy(oid, var->getName()->getValue(), var->getName()->getLength() * sizeof(UINT32));
37
38 // Get designated bridge and designated port for this port
39 SNMP_PDU *request = new SNMP_PDU(SNMP_GET_REQUEST, SnmpNewRequestId(), snmpVersion);
40
41 oid[10] = 8; // dot1dStpPortDesignatedBridge
42 request->bindVariable(new SNMP_Variable(oid, var->getName()->getLength()));
43
44 oid[10] = 9; // dot1dStpPortDesignatedPort
45 request->bindVariable(new SNMP_Variable(oid, var->getName()->getLength()));
46
47 SNMP_PDU *response = NULL;
48 UINT32 rcc = transport->doRequest(request, &response, SnmpGetDefaultTimeout(), 3);
49 delete request;
50 if (rcc == SNMP_ERR_SUCCESS)
51 {
52 if (response->getNumVariables() >= 2)
53 {
54 BYTE designatedBridge[16], designatedPort[4];
55 response->getVariable(0)->getRawValue(designatedBridge, 16);
56 response->getVariable(1)->getRawValue(designatedPort, 4);
57
58 // Usually bridge ID is a MAC address of one of bridge interfaces
59 // If this will not work, try to find bridge by bridge ID value
60 Node *bridge = FindNodeByMAC(&designatedBridge[2]);
61 if (bridge == NULL)
62 bridge = FindNodeByBridgeId(&designatedBridge[2]);
63 if ((bridge != NULL) && (bridge != node))
64 {
65 DbgPrintf(6, _T("STP: found designated bridge %s [%d] for node %s [%d] port %d"),
66 bridge->getName(), bridge->getId(), node->getName(), node->getId(), oid[11]);
67 Interface *ifLocal = node->findBridgePort(oid[11]);
68 if (ifLocal != NULL)
69 {
70 DbgPrintf(6, _T("STP: found local port %s [%d] for node %s [%d]"),
71 ifLocal->getName(), ifLocal->getId(), node->getName(), node->getId());
72 Interface *ifRemote = bridge->findBridgePort((UINT32)designatedPort[1]);
73 if (ifRemote != NULL)
74 {
75 DbgPrintf(6, _T("STP: found remote port %s [%d] on node %s [%d]"),
76 ifRemote->getName(), ifRemote->getId(), bridge->getName(), bridge->getId());
77
78 LL_NEIGHBOR_INFO info;
79 info.ifLocal = ifLocal->getIfIndex();
80 info.ifRemote = ifRemote->getIfIndex();
81 info.objectId = bridge->getId();
82 info.isPtToPt = true;
83 info.protocol = LL_PROTO_STP;
84 info.isCached = false;
85 ((LinkLayerNeighbors *)arg)->addConnection(&info);
86 }
87 else
88 {
89 DbgPrintf(6, _T("STP: bridge port number %d is invalid for node %s [%d]"), (UINT32)designatedPort[1], bridge->getName(), bridge->getId());
90 }
91 }
92 else
93 {
94 DbgPrintf(6, _T("STP: bridge port number %d is invalid for node %s [%d]"), oid[11], node->getName(), node->getId());
95 }
96 }
97 }
98 delete response;
99 }
100 else
101 {
102 }
103
104 return SNMP_ERR_SUCCESS;
105 }
106
107 /**
108 * Add STP-discovered neighbors
109 */
110 void AddSTPNeighbors(Node *node, LinkLayerNeighbors *nbs)
111 {
112 if (!(node->getFlags() & NF_IS_STP))
113 return;
114
115 DbgPrintf(5, _T("STP: collecting topology information for node %s [%d]"), node->getName(), node->getId());
116 nbs->setData(node);
117 node->callSnmpEnumerate(_T(".1.3.6.1.2.1.17.2.15.1.3"), STPPortListHandler, nbs);
118 DbgPrintf(5, _T("STP: finished collecting topology information for node %s [%d]"), node->getName(), node->getId());
119 }