/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.linkd;
import static org.opennms.core.utils.InetAddressUtils.str;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opennms.core.utils.LogUtils;
import org.opennms.netmgt.config.LinkdConfig;
import org.opennms.netmgt.config.SnmpPeerFactory;
import org.opennms.netmgt.linkd.scheduler.ReadyRunnable;
import org.opennms.netmgt.linkd.scheduler.Scheduler;
import org.opennms.netmgt.linkd.snmp.CiscoVlanTable;
import org.opennms.netmgt.linkd.snmp.FdbTableGet;
import org.opennms.netmgt.linkd.snmp.IntelVlanTable;
import org.opennms.netmgt.linkd.snmp.VlanCollectorEntry;
import org.opennms.netmgt.model.OnmsAtInterface;
import org.opennms.netmgt.model.OnmsStpInterface;
import org.opennms.netmgt.model.OnmsVlan;
import org.opennms.netmgt.snmp.SnmpAgentConfig;
/**
* This class is designed to discover link among nodes using the collected and
* the necessary SNMP information. When the class is initially constructed no
* information is used.
*
* @author <a href="mailto:antonio@opennms.it">Antonio Russo </a>
*/
public final class DiscoveryLink implements ReadyRunnable {
private static final int SNMP_IF_TYPE_ETHERNET = 6;
private static final int SNMP_IF_TYPE_PROP_VIRTUAL = 53;
private static final int SNMP_IF_TYPE_L2_VLAN = 135;
private static final int SNMP_IF_TYPE_L3_VLAN = 136;
private String packageName;
private List<NodeToNodeLink> m_links = new ArrayList<NodeToNodeLink>();
private List<MacToNodeLink> m_maclinks = new ArrayList<MacToNodeLink>();
private Map<Integer,LinkableNode> m_bridgeNodes = new HashMap<Integer,LinkableNode>();
private List<LinkableNode> m_routerNodes = new ArrayList<LinkableNode>();
private List<LinkableNode> m_cdpNodes = new ArrayList<LinkableNode>();
private List<LinkableNode> m_atNodes = new ArrayList<LinkableNode>();
// this is the list of MAC address just parsed by discovery process
private List<String> m_macsParsed = new ArrayList<String>();
// this is the list of MAC address excluded by discovery process
private List<String> macsExcluded = new ArrayList<String>();
// this is the list of atinterfaces for which to be discovery link
// here there aren't the bridge identifier because they should be discovered
// by main processes. This is used by addlinks method.
private Map<String,List<OnmsAtInterface>> m_macToAtinterface = new HashMap<String,List<OnmsAtInterface>>();
private boolean enableDownloadDiscovery = false;
private boolean discoveryUsingRoutes = true;
private boolean discoveryUsingCdp = true;
private boolean discoveryUsingBridge = true;
private boolean suspendCollection = false;
private boolean isRunned = false;
private boolean forceIpRouteDiscoveryOnEtherNet = false;
/**
* The scheduler object
*
*/
private Scheduler m_scheduler;
/**
* The interval default value 30 min
*/
private long snmp_poll_interval = 1800000;
/**
* The interval default value 5 min It is the time in ms after snmp
* collection is started
*
*/
private long discovery_interval = 300000;
/**
* The initial sleep time default value 10 min
*/
private long initial_sleep_time = 600000;
private Linkd m_linkd;
/**
* @param linkd the linkd to set
*/
public void setLinkd(Linkd linkd) {
this.m_linkd = linkd;
}
public Linkd getLinkd() {
return m_linkd;
}
/**
* Constructs a new DiscoveryLink object . The discovery does not occur
* until the <code>run</code> method is invoked.
*/
public DiscoveryLink() {
super();
}
/**
* <p>
* Performs link discovery for the Nodes and save info in
* DatalinkInterface table on DataBase
* <p>
* No synchronization is performed, so if this is used in a separate thread
* context synchronization must be added.
* </p>
*/
public void run() {
if (suspendCollection) {
LogUtils.warnf(this, "run: linkd collections are suspended!");
} else {
Collection<LinkableNode> linkableNodes = m_linkd.getLinkableNodesOnPackage(getPackageName());
LogUtils.debugf(this, "run: LinkableNodes/package found: %d/%s", linkableNodes.size(), getPackageName());
LogUtils.debugf(this, "run: discoveryUsingBridge/discoveryUsingCdp/discoveryUsingRoutes: %b/%b/%b", discoveryUsingBridge, discoveryUsingCdp, discoveryUsingRoutes);
LogUtils.debugf(this, "run: enableDownloadDiscovery: %b", enableDownloadDiscovery);
for (final LinkableNode linkableNode : linkableNodes) {
LogUtils.debugf(this, "run: Iterating on LinkableNode's found node with ID %d", linkableNode.getNodeId());
if (linkableNode.isBridgeNode() && discoveryUsingBridge) {
m_bridgeNodes.put(new Integer(linkableNode.getNodeId()), linkableNode);
}
if (linkableNode.hasCdpInterfaces() && discoveryUsingCdp) {
m_cdpNodes.add(linkableNode);
}
if (linkableNode.hasRouteInterfaces() && discoveryUsingRoutes) {
m_routerNodes.add(linkableNode);
}
if (linkableNode.hasAtInterfaces()) {
m_atNodes.add(linkableNode);
}
}
populateMacToAtInterface();
//now perform operation to complete
if (enableDownloadDiscovery) {
LogUtils.infof(this, "run: fetching further unknown MAC address SNMP bridge table info");
parseBridgeNodes();
} else {
LogUtils.infof(this, "run: skipping fetch of further unknown MAC address SNMP bridge table info");
}
// First of all use quick methods to get backbone ports for speeding up the link discovery
if (m_cdpNodes.size() > 0) {
LogUtils.infof(this, "run: finding links among nodes using Cisco Discovery Protocol");
}
// Try Cisco Discovery Protocol to found link among all nodes
// Add CDP info for backbones ports
for (final LinkableNode curNode : m_cdpNodes) {
int curCdpNodeId = curNode.getNodeId();
final InetAddress curCdpIpAddr = curNode.getSnmpPrimaryIpAddr();
LogUtils.infof(this, "run: parsing nodeid %d IP address %s with %d CDP interfaces.", curCdpNodeId, curCdpIpAddr, curNode.getCdpInterfaces().size());
for (final CdpInterface cdpIface : curNode.getCdpInterfaces()) {
final int cdpIfIndex = cdpIface.getCdpIfIndex();
if (cdpIfIndex < 0) {
LogUtils.warnf(this, "run: found not valid CDP IfIndex %d. Skipping.", cdpIfIndex);
continue;
}
LogUtils.debugf(this, "run: found CDP ifindex %d", cdpIfIndex);
final InetAddress targetIpAddr = cdpIface.getCdpTargetIpAddr();
final String hostAddress = str(targetIpAddr);
if (!m_linkd.isInterfaceInPackage(targetIpAddr, getPackageName()))
{
LogUtils.debugf(this, "run: IP address %s Not in package: %s. Skipping.", hostAddress, getPackageName());
continue;
}
final int targetCdpNodeId = cdpIface.getCdpTargetNodeId();
if (targetCdpNodeId == -1) {
LogUtils.debugf(this, "run: no node id found for IP address %s. Skipping.", hostAddress);
continue;
}
LogUtils.debugf(this, "run: found nodeid/CDP target ipaddress: %d:%s", targetCdpNodeId, str(targetIpAddr));
if (targetCdpNodeId == curCdpNodeId) {
LogUtils.debugf(this, "run: node id found for IP address %s is itself. Skipping.", hostAddress);
continue;
}
final int cdpDestIfindex = cdpIface.getCdpTargetIfIndex();
if (cdpDestIfindex < 0) {
LogUtils.warnf(this, "run: found not valid CDP destination IfIndex %d. Skipping.", cdpDestIfindex);
continue;
}
LogUtils.debugf(this, "run: found CDP target ifindex %d", cdpDestIfindex);
LogUtils.debugf(this, "run: parsing CDP link: nodeid=%d ifindex=%d nodeparentid=%d parentifindex=%d", curCdpNodeId, cdpIfIndex, targetCdpNodeId, cdpDestIfindex);
boolean add = false;
if (curNode.isBridgeNode() && isBridgeNode(targetCdpNodeId)) {
LinkableNode targetNode = m_bridgeNodes.get(new Integer(targetCdpNodeId));
add = parseCdpLinkOn(curNode, cdpIfIndex,targetNode, cdpDestIfindex);
LogUtils.debugf(this, "run: both node are bridge nodes! Adding: %b", add);
} else if (curNode.isBridgeNode()) {
LogUtils.debugf(this, "run: source node is bridge node, target node is not bridge node! Adding: %b", add);
add = parseCdpLinkOn(curNode,cdpIfIndex,targetCdpNodeId);
} else if (isBridgeNode(targetCdpNodeId)) {
LogUtils.debugf(this, "run: source node is not bridge node, target node is bridge node! Adding: %b", add);
LinkableNode targetNode = m_bridgeNodes.get(new Integer(targetCdpNodeId));
add = parseCdpLinkOn(targetNode,cdpDestIfindex,curCdpNodeId);
} else {
LogUtils.debugf(this, "run: no node is bridge node! Adding CDP link");
add = true;
}
// now add the CDP link
if (add) {
final NodeToNodeLink lk = new NodeToNodeLink(targetCdpNodeId, cdpDestIfindex);
lk.setNodeparentid(curCdpNodeId);
lk.setParentifindex(cdpIfIndex);
LogUtils.infof(this, "run: CDP link added: %s", lk.toString());
addNodetoNodeLink(lk);
}
}
LogUtils.infof(this, "run: done parsing nodeid %d IP address %s with %d CDP interfaces.", curCdpNodeId, curCdpIpAddr, curNode.getCdpInterfaces().size());
}
if (m_cdpNodes.size() > 0) {
LogUtils.infof(this, "run: done finding links among nodes using Cisco Discovery Protocol");
}
// try get backbone links between switches using STP info
// and store information in Bridge class
if (m_bridgeNodes.size() > 0) {
LogUtils.infof(this, "run: trying to find backbone ethernet links among bridge nodes using Spanning Tree Protocol");
}
for (final LinkableNode curNode : m_bridgeNodes.values()) {
final int curNodeId = curNode.getNodeId();
final InetAddress cupIpAddr = curNode.getSnmpPrimaryIpAddr();
LogUtils.infof(this, "run: parsing bridge nodeid %d IP address %s with %d VLANs", curNodeId, str(cupIpAddr), curNode.getStpInterfaces().size());
for (final Map.Entry<String,List<OnmsStpInterface>> me : curNode.getStpInterfaces().entrySet()) {
final String vlan = me.getKey();
final String curBaseBridgeAddress = curNode.getBridgeIdentifier(vlan);
LogUtils.debugf(this, "run: found bridge identifier %s", curBaseBridgeAddress);
String designatedRoot = null;
if (curNode.hasStpRoot(vlan)) {
designatedRoot = curNode.getStpRoot(vlan);
} else {
LogUtils.debugf(this, "run: designated root bridge identifier not found. Skipping %s", curBaseBridgeAddress);
continue;
}
if (designatedRoot == null || designatedRoot.equals("0000000000000000")) {
LogUtils.warnf(this, "run: designated root is invalid, skipping: %s", designatedRoot);
continue;
}
// check if designated
// bridge is itself
// if bridge is STP root bridge itself exiting
// searching on linkablesnmpnodes
if (curNode.isBridgeIdentifier(designatedRoot.substring(4))) {
LogUtils.debugf(this, "run: STP designated root is the bridge itself. Skipping.");
continue;
}
// Now parse STP bridge port info to get designated bridge
LogUtils.debugf(this, "run: STP designated root is another bridge. %s Parsing STP Interface", designatedRoot);
for (final OnmsStpInterface stpIface : me.getValue()) {
// the bridge port number
final int stpbridgeport = stpIface.getBridgePort();
// if port is a backbone port continue
if (curNode.isBackBoneBridgePort(stpbridgeport)) {
LogUtils.debugf(this, "run: bridge port %d already found. Skipping.", stpbridgeport);
continue;
}
final String stpPortDesignatedPort = stpIface.getStpPortDesignatedPort();
final String stpPortDesignatedBridge = stpIface.getStpPortDesignatedBridge();
LogUtils.debugf(this, "run: parsing bridge port %d with STP designated bridge %s and STP designated port %s", stpbridgeport, stpPortDesignatedBridge, stpPortDesignatedPort);
if (stpPortDesignatedBridge == null || stpPortDesignatedBridge.equals("0000000000000000") || stpPortDesignatedBridge.equals("")) {
LogUtils.warnf(this, "run: designated bridge is invalid, skipping: %s", stpPortDesignatedBridge);
continue;
}
if (curNode.isBridgeIdentifier(stpPortDesignatedBridge.substring(4))) {
LogUtils.debugf(this, "run: designated bridge for port %d is bridge itself", stpbridgeport);
continue;
}
if (stpPortDesignatedPort == null || stpPortDesignatedPort.equals("0000")) {
LogUtils.warnf(this, "run: designated port is invalid: %s", stpPortDesignatedPort);
continue;
}
// A Port Identifier shall be encoded as two octets,
// taken to represent an unsigned binary number. If
// two Port Identifiers are numerically compared, the
// lesser number denotes the Port of better priority.
// The more significant octet of a Port Identifier is
// a settable priority component that permits the
// relative priority of Ports on the same Bridge to be
// managed (17.13.7 and Clause 14). The less
// significant twelve bits is the Port Number
// expressed as an unsigned binary number. The value 0
// is not used as a Port Number. NOTE -- The number of
// bits that are considered to be part of the Port
// Number (12 bits) differs from the 1998 and prior
// versions of this standard (formerly, the priority
// component was 8 bits and the Port Number component
// also 8 bits). This change acknowledged that modern
// switched LAN infrastructures call for increasingly
// large numbers of Ports to be supported in a single
// Bridge. To maintain management compatibility with
// older implementations, the priority component is
// still considered, for management purposes, to be an
// 8-bit value, but the values that it can be set to
// are restricted to those where the least significant
// 4 bits are zero (i.e., only the most significant 4
// bits are settable).
int designatedbridgeport = Integer.parseInt(stpPortDesignatedPort.substring(1), 16);
// try to see if designated bridge is linkable SNMP node
final LinkableNode designatedNode = getNodeFromMacIdentifierOfBridgeNode(stpPortDesignatedBridge.substring(4));
if (designatedNode == null) {
LogUtils.debugf(this, "run: no nodeid found for STP bridge address %s. Nothing to save.", stpPortDesignatedBridge);
continue; // no saving info if no nodeid
}
final int designatednodeid = designatedNode.getNodeId();
LogUtils.debugf(this, "run: found designated nodeid %d", designatednodeid);
// test if there are other bridges between this link
// USING MAC ADDRESS FORWARDING TABLE
if (!isNearestBridgeLink(curNode, stpbridgeport, designatedNode, designatedbridgeport)) {
LogUtils.debugf(this, "run: other bridge found between nodes. No links to save!");
continue; // no saving info if no nodeid
}
// this is a backbone port so try adding to Bridge class
// get the ifindex on node
final int curIfIndex = curNode.getIfindex(stpbridgeport);
if (curIfIndex == -1) {
LogUtils.warnf(this, "run: got invalid ifindex on node: %s", curNode.toString());
continue;
}
final int designatedifindex = designatedNode.getIfindex(designatedbridgeport);
if (designatedifindex == -1) {
LogUtils.warnf(this, "run: got invalid ifindex on designated node: %s", designatedNode.toString());
continue;
}
LogUtils.debugf(this, "run: backbone port found for node %d. Adding to bridge %d.", curNodeId, stpbridgeport);
curNode.addBackBoneBridgePorts(stpbridgeport);
m_bridgeNodes.put(new Integer(curNodeId), curNode);
LogUtils.debugf(this, "run: backbone port found for node %d. Adding to helper class BB port bridge port %d.", designatednodeid, designatedbridgeport);
designatedNode.addBackBoneBridgePorts(designatedbridgeport);
m_bridgeNodes.put(new Integer(designatednodeid), designatedNode);
LogUtils.debugf(this, "run: adding links on BB bridge port %d", designatedbridgeport);
addLinks(getMacsOnBridgeLink(curNode, stpbridgeport, designatedNode, designatedbridgeport),curNodeId,curIfIndex);
// writing to db using class
// DbDAtaLinkInterfaceEntry
final NodeToNodeLink lk = new NodeToNodeLink(curNodeId, curIfIndex);
lk.setNodeparentid(designatednodeid);
lk.setParentifindex(designatedifindex);
LogUtils.infof(this, "run: saving STP bridge link: " + lk.toString());
addNodetoNodeLink(lk);
}
}
LogUtils.infof(this, "run: done parsing bridge nodeid %d IP address %s with %d VLANs", curNodeId, str(cupIpAddr), curNode.getStpInterfaces().size());
}
if (m_bridgeNodes.size() > 0) {
LogUtils.infof(this, "run: done finding backbone ethernet links among bridge nodes using Spanning Tree Protocol");
}
// finding links using MAC address on ports
if (m_bridgeNodes.size() > 0) {
LogUtils.infof(this, "run: trying to find links using MAC Address Forwarding Table");
}
for (final LinkableNode curNode : m_bridgeNodes.values()) {
final int curNodeId = curNode.getNodeId();
LogUtils.infof(this, "run: parsing bridge node with ID %d", curNodeId);
for (final Integer curBridgePort : curNode.getPortMacs().keySet()) {
LogUtils.debugf(this, "run: parsing bridge port %d with MAC address %s", curBridgePort, curNode.getMacAddressesOnBridgePort(curBridgePort).toString());
if (curNode.isBackBoneBridgePort(curBridgePort)) {
LogUtils.debugf(this, "run: Port %d is a backbone bridge port. Skipping.", curBridgePort);
continue;
}
final int curIfIndex = curNode.getIfindex(curBridgePort);
if (curIfIndex == -1) {
LogUtils.warnf(this, "run: got invalid ifIndex on bridge port %d", curBridgePort);
continue;
}
// First get the MAC addresses on bridge port
final Set<String> macs = curNode.getMacAddressesOnBridgePort(curBridgePort);
// Then find the bridges whose MAC addresses are learned on bridge port
final List<LinkableNode> bridgesOnPort = getBridgesFromMacs(macs);
if (bridgesOnPort.isEmpty()) {
LogUtils.debugf(this, "run: no bridge info found on port %d. Saving MACs.", curBridgePort);
addLinks(macs, curNodeId, curIfIndex);
} else {
// a bridge MAC address was found on port so you should analyze what happens
LogUtils.debugf(this, "run: bridge info found on port %d. Finding nearest.", curBridgePort);
// one among these bridges should be the node more close to the curnode, curport
for (final LinkableNode endNode : bridgesOnPort) {
final int endNodeid = endNode.getNodeId();
final int endBridgePort = getBridgePortOnEndBridge(curNode, endNode);
// The bridge port should be valid! This control is not properly done
if (endBridgePort == -1) {
LogUtils.warnf(this, "run: no valid port found on bridge nodeid %d for node bridge identifiers nodeid %d. Skipping.", endNodeid, curNodeId);
continue;
}
// Try to found a new
final boolean isTargetNode = isNearestBridgeLink(curNode, curBridgePort, endNode, endBridgePort);
if (!isTargetNode) continue;
final int endIfindex = endNode.getIfindex(endBridgePort);
if (endIfindex == -1) {
LogUtils.warnf(this, "run: got invalid ifindex on designated bridge port %d", endBridgePort);
continue;
}
LogUtils.debugf(this, "run: backbone port found for node %d. Adding backbone port %d to bridge", curNodeId, curBridgePort);
curNode.addBackBoneBridgePorts(curBridgePort);
m_bridgeNodes.put(curNodeId, curNode);
LogUtils.debugf(this, "run: backbone port found for node %d. Adding to helper class backbone port bridge port %d", endNodeid, endBridgePort);
endNode.addBackBoneBridgePorts(endBridgePort);
m_bridgeNodes.put(endNodeid, endNode);
// finding links between two backbone ports
addLinks(getMacsOnBridgeLink(curNode, curBridgePort, endNode, endBridgePort),curNodeId,curIfIndex);
final NodeToNodeLink lk = new NodeToNodeLink(curNodeId, curIfIndex);
lk.setNodeparentid(endNodeid);
lk.setParentifindex(endIfindex);
LogUtils.infof(this, "run: saving bridge link: " + lk.toString());
addNodetoNodeLink(lk);
}
}
}
LogUtils.infof(this, "run: done parsing bridge node with ID %d", curNodeId);
}
if (m_bridgeNodes.size() > 0) {
LogUtils.infof(this, "run: done finding links using MAC Address Forwarding Table");
}
// fourth find inter-router links,
// this part could have several special function to get inter-router
// links, but at the moment we worked much on switches.
// In future we can try to extend this part.
if (m_routerNodes.size() > 0) {
LogUtils.infof(this, "run: finding non-ethernet links on Router nodes");
}
for (final LinkableNode curNode : m_routerNodes) {
final int curNodeId = curNode.getNodeId();
InetAddress curIpAddr = curNode.getSnmpPrimaryIpAddr();
LogUtils.infof(this, "run: parsing router node with ID %d IP address %s and %d router interfaces", curNodeId, str(curIpAddr), curNode.getRouteInterfaces().size());
for (final RouterInterface routeIface : curNode.getRouteInterfaces()) {
LogUtils.debugf(this, "run: parsing RouterInterface: " + routeIface.toString());
if (routeIface.getMetric() == -1) {
LogUtils.warnf(this, "run: Router interface has invalid metric %d. Skipping.", routeIface.getMetric());
continue;
}
if (forceIpRouteDiscoveryOnEtherNet) {
LogUtils.debugf(this, "run: forceIpRouteDiscoveryOnEtherNet is set, skipping validation of the SNMP interface type");
} else {
final int snmpiftype = routeIface.getSnmpiftype();
LogUtils.debugf(this, "run: force IP route discovery getting SnmpIfType: " + snmpiftype);
if (snmpiftype == SNMP_IF_TYPE_ETHERNET) {
LogUtils.debugf(this, "run: Ethernet interface for nodeid %d. Skipping.", curNodeId);
continue;
} else if (snmpiftype == SNMP_IF_TYPE_PROP_VIRTUAL) {
LogUtils.debugf(this, "run: PropVirtual interface for nodeid %d. Skipping.", curNodeId);
continue;
} else if (snmpiftype == SNMP_IF_TYPE_L2_VLAN) {
LogUtils.debugf(this, "run: Layer2 VLAN interface for nodeid %d. Skipping.", curNodeId);
continue;
} else if (snmpiftype == SNMP_IF_TYPE_L3_VLAN) {
LogUtils.debugf(this, "run: Layer3 VLAN interface for nodeid %d. Skipping.", curNodeId);
continue;
} else if (snmpiftype == -1) {
LogUtils.debugf(this, "run: interface on node %d has unknown snmpiftype %d. Skipping.", curNodeId, snmpiftype);
continue;
}
}
final InetAddress nexthop = routeIface.getNextHop();
final String hostAddress = str(nexthop);
if (hostAddress.equals("0.0.0.0")) {
LogUtils.debugf(this, "run: nexthop address is broadcast address %s. Skipping.", hostAddress);
// FIXME this should be further analyzed
// working on routeDestNet you can find hosts that
// are directly connected with the destination network
// This happens when static routing is made like this:
// route 10.3.2.0 255.255.255.0 Serial0
// so the router broadcasts on Serial0
continue;
}
if (nexthop.isLoopbackAddress()) {
LogUtils.debugf(this, "run: nexthop address is localhost address %s. Skipping.", hostAddress);
continue;
}
if (!m_linkd.isInterfaceInPackage(nexthop, getPackageName())) {
LogUtils.debugf(this, "run: nexthop address is not in package %s/%s. Skipping.", hostAddress, getPackageName());
continue;
}
final int nextHopNodeid = routeIface.getNextHopNodeid();
if (nextHopNodeid == -1) {
LogUtils.debugf(this, "run: no node id found for IP next hop address %s. Skipping.", hostAddress);
continue;
}
if (nextHopNodeid == curNodeId) {
LogUtils.debugf(this, "run: node id found for IP next hop address %s is itself. Skipping.", hostAddress);
continue;
}
int ifindex = routeIface.getIfindex();
if (ifindex == 0) {
LogUtils.debugf(this, "run: route interface has ifindex %d, trying to get ifIndex from nextHopNet: %s", ifindex, routeIface.getNextHopNet());
ifindex = getIfIndexFromRouter(curNode, routeIface.getNextHopNet());
if (ifindex == -1) {
LogUtils.debugf(this, "run: found not correct ifindex %d. Skipping.", ifindex);
continue;
} else {
LogUtils.debugf(this, "run: found correct ifindex %d.", ifindex);
}
}
// Saving link also when ifindex = -1 (not found)
final NodeToNodeLink lk = new NodeToNodeLink(nextHopNodeid, routeIface.getNextHopIfindex());
lk.setNodeparentid(curNodeId);
lk.setParentifindex(ifindex);
LogUtils.infof(this, "run: saving route link: " + lk.toString());
addNodetoNodeLink(lk);
}
LogUtils.infof(this, "run: done parsing router node with ID %d IP address %s and %d router interfaces", curNodeId, str(curIpAddr), curNode.getRouteInterfaces().size());
}
if (m_routerNodes.size() > 0) {
LogUtils.infof(this, "run: done finding non-ethernet links on Router nodes");
}
m_bridgeNodes.clear();
m_routerNodes.clear();
m_cdpNodes.clear();
m_macsParsed.clear();
macsExcluded.clear();
m_macToAtinterface.clear();
m_atNodes.clear();
m_linkd.updateDiscoveryLinkCollection(this);
m_links.clear();
m_maclinks.clear();
}
// rescheduling activities
isRunned = true;
reschedule();
}
protected void populateMacToAtInterface() {
LogUtils.debugf(this, "populateMacToAtInterface: using atNodes to populate macToAtinterface");
for (final LinkableNode curNode : m_atNodes) {
for (final OnmsAtInterface at : curNode.getAtInterfaces()) {
int nodeid = at.getNode().getId();
final String macAddress = at.getMacAddress();
LogUtils.debugf(this, "populateMacToAtInterface: Parsing AtInterface nodeid/ipaddr/macaddr: %d/%s/%s", nodeid, str(at.getIpAddress()), macAddress);
if (!m_linkd.isInterfaceInPackage(at.getIpAddress(), getPackageName())) {
LogUtils.debugf(this, "populateMacToAtInterface: at interface: %s does not belong to package: %s! Not adding to discoverable atinterface.", str(at.getIpAddress()), getPackageName());
macsExcluded.add(macAddress);
continue;
}
if (isMacIdentifierOfBridgeNode(macAddress)) {
LogUtils.debugf(this, "populateMacToAtInterface: AtInterface %s belongs to bridge node! Not adding to discoverable atinterface.", macAddress);
macsExcluded.add(macAddress);
continue;
}
if ((macAddress.indexOf("00000c07ac") == 0) || (macAddress.indexOf("00000c9ff") == 0)) {
LogUtils.debugf(this, "populateMacToAtInterface: AtInterface %s is Cisco HSRP address! Not adding to discoverable atinterface.", macAddress);
macsExcluded.add(macAddress);
continue;
}
List<OnmsAtInterface> ats = m_macToAtinterface.get(macAddress);
if (ats == null) ats = new ArrayList<OnmsAtInterface>();
LogUtils.debugf(this, "populateMacToAtInterface: Adding to discoverable atinterface.");
ats.add(at);
m_macToAtinterface.put(macAddress, ats);
LogUtils.debugf(this, "populateMacToAtInterface: MAC %s now has atinterface reference: %d", macAddress, ats.size());
}
}
LogUtils.debugf(this, "populateMacToAtInterface: end populateMacToAtinterface");
}
private static int getIfIndexFromRouter(LinkableNode parentnode, InetAddress nextHopNet) {
if (!parentnode.hasRouteInterfaces())
return -1;
for (RouterInterface curIface : parentnode.getRouteInterfaces()) {
if (curIface.getMetric() == -1) {
continue;
}
int ifindex = curIface.getIfindex();
if (ifindex == 0 || ifindex == -1)
continue;
if (curIface.getRouteNet().equals(nextHopNet)) return ifindex;
}
return -1;
}
/**
*
* @param nodeid
* @return LinkableSnmpNode or null if not found
*/
boolean isBridgeNode(int nodeid) {
for (final LinkableNode curNode : m_bridgeNodes.values()) {
if (nodeid == curNode.getNodeId())
return true;
}
return false;
}
/**
*
* @param nodeid
* @return true if found
*/
boolean isRouterNode(int nodeid) {
for (final LinkableNode curNode : m_routerNodes) {
if (nodeid == curNode.getNodeId())
return true;
}
return false;
}
/**
*
* @param nodeid
* @return true if found
*/
boolean isCdpNode(int nodeid) {
for (LinkableNode curNode : m_cdpNodes) {
if (nodeid == curNode.getNodeId())
return true;
}
return false;
}
private boolean isEndBridgePort(LinkableNode bridge, int bridgeport){
Set<String> macsOnBridge = bridge.getMacAddressesOnBridgePort(bridgeport);
if (macsOnBridge == null || macsOnBridge.isEmpty())
return true;
for (final String macaddr : macsOnBridge) {
if (isMacIdentifierOfBridgeNode(macaddr)) return false;
}
return true;
}
private boolean isNearestBridgeLink(LinkableNode bridge1, int bp1,
LinkableNode bridge2, int bp2) {
boolean hasbridge2forwardingRule = false;
Set<String> macsOnBridge2 = bridge2.getMacAddressesOnBridgePort(bp2);
Set<String> macsOnBridge1 = bridge1.getMacAddressesOnBridgePort(bp1);
if (macsOnBridge2 == null || macsOnBridge1 == null)
return false;
if (macsOnBridge2.isEmpty() || macsOnBridge1.isEmpty())
return false;
for (final String curMacOnBridge1 : macsOnBridge1) {
// if MAC address is bridge identifier of bridge 2 continue
if (bridge2.isBridgeIdentifier(curMacOnBridge1)) {
hasbridge2forwardingRule = true;
continue;
}
// if MAC address is itself identifier of bridge1 continue
if (bridge1.isBridgeIdentifier(curMacOnBridge1))
continue;
// then no identifier of bridge one no identifier of bridge 2
// bridge 2 contains
if (macsOnBridge2.contains(curMacOnBridge1)
&& isMacIdentifierOfBridgeNode(curMacOnBridge1))
return false;
}
return hasbridge2forwardingRule;
}
private Set<String> getMacsOnBridgeLink(LinkableNode bridge1, int bp1,
LinkableNode bridge2, int bp2) {
Set<String> macsOnLink = new HashSet<String>();
Set<String> macsOnBridge1 = bridge1.getMacAddressesOnBridgePort(bp1);
Set<String> macsOnBridge2 = bridge2.getMacAddressesOnBridgePort(bp2);
if (macsOnBridge2 == null || macsOnBridge1 == null)
return null;
if (macsOnBridge2.isEmpty() || macsOnBridge1.isEmpty())
return null;
for (final String curMacOnBridge1 : macsOnBridge1) {
if (bridge2.isBridgeIdentifier(curMacOnBridge1))
continue;
if (macsOnBridge2.contains(curMacOnBridge1))
macsOnLink.add(curMacOnBridge1);
}
return macsOnLink;
}
private boolean isMacIdentifierOfBridgeNode(String macAddress) {
for (final LinkableNode curNode : m_bridgeNodes.values()) {
if (curNode.isBridgeIdentifier(macAddress))
return true;
}
return false;
}
private LinkableNode getNodeFromMacIdentifierOfBridgeNode(final String macAddress) {
for (final LinkableNode curNode : m_bridgeNodes.values()) {
if (curNode.isBridgeIdentifier(macAddress))
return curNode;
}
return null;
}
private List<LinkableNode> getBridgesFromMacs(final Set<String> macs) {
List<LinkableNode> bridges = new ArrayList<LinkableNode>();
for (final LinkableNode curNode : m_bridgeNodes.values()) {
for (final String curBridgeIdentifier : curNode.getBridgeIdentifiers()) {
if (macs.contains((curBridgeIdentifier)))
bridges.add(curNode);
}
}
return bridges;
}
private int getBridgePortOnEndBridge(final LinkableNode startBridge, final LinkableNode endBridge) {
int port = -1;
for (final String curBridgeIdentifier : startBridge.getBridgeIdentifiers()) {
LogUtils.debugf(this, "getBridgePortOnEndBridge: parsing bridge identifier "
+ curBridgeIdentifier);
if (endBridge.hasMacAddress(curBridgeIdentifier)) {
for (final Integer p : endBridge.getBridgePortsFromMac(curBridgeIdentifier)) {
port = p;
if (endBridge.isBackBoneBridgePort(port)) {
LogUtils.debugf(this, "getBridgePortOnEndBridge: found backbone bridge port "
+ port
+ " .... Skipping.");
continue;
}
if (port == -1) {
LogUtils.debugf(this, "getBridgePortOnEndBridge: no port found on bridge nodeid "
+ endBridge.getNodeId()
+ " for node bridge identifiers nodeid "
+ startBridge.getNodeId()
+ " . .....Skipping.");
continue;
}
LogUtils.debugf(this, "getBridgePortOnEndBridge: using MAC address table found bridge port "
+ port
+ " on node "
+ endBridge.getNodeId());
return port;
}
} else {
LogUtils.debugf(this, "getBridgePortOnEndBridge: bridge identifier not found on node "
+ endBridge.getNodeId());
}
}
return -1;
}
/**
* Return the Scheduler
*
* @return a {@link org.opennms.netmgt.linkd.scheduler.Scheduler} object.
*/
public Scheduler getScheduler() {
return m_scheduler;
}
/**
* Set the Scheduler
*
* @param scheduler a {@link org.opennms.netmgt.linkd.scheduler.Scheduler} object.
*/
public void setScheduler(Scheduler scheduler) {
m_scheduler = scheduler;
}
/**
* This Method is called when DiscoveryLink is initialized
*/
public void schedule() {
if (m_scheduler == null)
throw new IllegalStateException(
"schedule: Cannot schedule a service whose scheduler is set to null");
m_scheduler.schedule(snmp_poll_interval + discovery_interval
+ initial_sleep_time, this);
}
/**
* Schedule again the job
*
* @return
*/
private void reschedule() {
if (m_scheduler == null)
throw new IllegalStateException(
"rescedule: Cannot schedule a service whose scheduler is set to null");
m_scheduler.schedule(snmp_poll_interval, this);
}
/**
* <p>getInitialSleepTime</p>
*
* @return Returns the initial_sleep_time.
*/
public long getInitialSleepTime() {
return initial_sleep_time;
}
/**
* <p>setInitialSleepTime</p>
*
* @param initial_sleep_time
* The initial_sleep_timeto set.
*/
public void setInitialSleepTime(long initial_sleep_time) {
this.initial_sleep_time = initial_sleep_time;
}
/**
* <p>isReady</p>
*
* @return a boolean.
*/
public boolean isReady() {
return true;
}
/**
* <p>getDiscoveryInterval</p>
*
* @return Returns the discovery_link_interval.
*/
public long getDiscoveryInterval() {
return discovery_interval;
}
/**
* <p>setSnmpPollInterval</p>
*
* @param interval
* The discovery_link_interval to set.
*/
public void setSnmpPollInterval(long interval) {
this.snmp_poll_interval = interval;
}
/**
* <p>getSnmpPollInterval</p>
*
* @return Returns the discovery_link_interval.
*/
public long getSnmpPollInterval() {
return snmp_poll_interval;
}
/**
* <p>setDiscoveryInterval</p>
*
* @param interval
* The discovery_link_interval to set.
*/
public void setDiscoveryInterval(long interval) {
this.discovery_interval = interval;
}
/**
* <p>Getter for the field <code>links</code>.</p>
*
* @return an array of {@link org.opennms.netmgt.linkd.NodeToNodeLink} objects.
*/
public NodeToNodeLink[] getLinks() {
return m_links.toArray(new NodeToNodeLink[0]);
}
/**
* <p>getMacLinks</p>
*
* @return an array of {@link org.opennms.netmgt.linkd.MacToNodeLink} objects.
*/
public MacToNodeLink[] getMacLinks() {
return m_maclinks.toArray(new MacToNodeLink[0]);
}
/**
* <p>isSuspended</p>
*
* @return Returns the suspendCollection.
*/
public boolean isSuspended() {
return suspendCollection;
}
/**
* <p>suspend</p>
*/
public void suspend() {
this.suspendCollection = true;
}
/**
* <p>wakeUp</p>
*/
public void wakeUp() {
this.suspendCollection = false;
}
/**
* <p>unschedule</p>
*/
public void unschedule() {
if (m_scheduler == null)
throw new IllegalStateException(
"unschedule: Cannot schedule a service whose scheduler is set to null");
if (isRunned) {
m_scheduler.unschedule(this, snmp_poll_interval);
} else {
m_scheduler.unschedule(this, snmp_poll_interval
+ initial_sleep_time + discovery_interval);
}
}
private boolean parseCdpLinkOn(LinkableNode node1,int ifindex1,
int nodeid2) {
int bridgeport = node1.getBridgePort(ifindex1);
if (node1.isBackBoneBridgePort(bridgeport)) {
LogUtils.debugf(this, "parseCdpLinkOn: node/backbone bridge port "
+ node1.getNodeId() +"/" +bridgeport
+ " already parsed. Skipping.");
return false;
}
if (isEndBridgePort(node1, bridgeport)) {
node1.addBackBoneBridgePorts(bridgeport);
m_bridgeNodes.put(node1.getNodeId(), node1);
Set<String> macs = node1.getMacAddressesOnBridgePort(bridgeport);
addLinks(macs,node1.getNodeId(),ifindex1);
} else {
LogUtils.warnf(this, "parseCdpLinkOn: link cannot be saved. Skipping.");
return false;
}
return true;
}
private boolean parseCdpLinkOn(LinkableNode node1,int ifindex1,
LinkableNode node2,int ifindex2) {
int bridgeport1 = node1.getBridgePort(ifindex1);
if (node1.isBackBoneBridgePort(bridgeport1)) {
LogUtils.debugf(this, "parseCdpLinkOn: backbone bridge port "
+ bridgeport1
+ " already parsed. Skipping.");
return false;
}
int bridgeport2 = node2
.getBridgePort(ifindex2);
if (node2.isBackBoneBridgePort(bridgeport2)) {
LogUtils.debugf(this, "parseCdpLinkOn: backbone bridge port "
+ bridgeport2
+ " already parsed. Skipping.");
return false;
}
if (isNearestBridgeLink(node1, bridgeport1,
node2, bridgeport2)) {
node1.addBackBoneBridgePorts(bridgeport1);
m_bridgeNodes.put(node1.getNodeId(), node1);
node2.addBackBoneBridgePorts(bridgeport2);
m_bridgeNodes.put(node2.getNodeId(),node2);
LogUtils.debugf(this, "parseCdpLinkOn: Adding node on links.");
addLinks(getMacsOnBridgeLink(node1,
bridgeport1, node2, bridgeport2),node1.getNodeId(),ifindex1);
} else {
LogUtils.debugf(this, "parseCdpLinkOn: link found not on nearest. Skipping.");
return false;
}
return true;
}
private void addNodetoNodeLink(NodeToNodeLink nnlink) {
if (nnlink == null)
{
LogUtils.warnf(this, "addNodetoNodeLink: node link is null.");
return;
}
for (NodeToNodeLink curNnLink : m_links) {
if (curNnLink.equals(nnlink)) {
LogUtils.infof(this, "addNodetoNodeLink: link %s exists, not adding", nnlink.toString());
return;
}
}
LogUtils.debugf(this, "addNodetoNodeLink: adding link %s", nnlink.toString());
m_links.add(nnlink);
}
private void addLinks(Set<String> macs,int nodeid,int ifindex) {
if (macs == null || macs.isEmpty()) {
LogUtils.debugf(this, "addLinks: MAC address list on link is empty.");
} else {
for (String curMacAddress : macs) {
if (m_macsParsed.contains(curMacAddress)) {
LogUtils.warnf(this, "addLinks: MAC address "
+ curMacAddress
+ " just found on other bridge port! Skipping...");
continue;
}
if (macsExcluded.contains(curMacAddress)) {
LogUtils.warnf(this, "addLinks: MAC address "
+ curMacAddress
+ " is excluded from discovery package! Skipping...");
continue;
}
if (m_macToAtinterface.containsKey(curMacAddress)) {
List<OnmsAtInterface> ats = m_macToAtinterface.get(curMacAddress);
for (OnmsAtInterface at : ats) {
NodeToNodeLink lNode = new NodeToNodeLink(at.getNode().getId(),at.getIfIndex());
lNode.setNodeparentid(nodeid);
lNode.setParentifindex(ifindex);
addNodetoNodeLink(lNode);
}
} else {
LogUtils.debugf(this, "addLinks: not find nodeid for ethernet MAC address %s found on node/ifindex %d/%d", curMacAddress, nodeid, ifindex);
MacToNodeLink lMac = new MacToNodeLink(curMacAddress);
lMac.setNodeparentid(nodeid);
lMac.setParentifindex(ifindex);
m_maclinks.add(lMac);
}
m_macsParsed.add(curMacAddress);
}
}
}
/** {@inheritDoc} */
public boolean equals(ReadyRunnable r) {
return (r instanceof DiscoveryLink && this.getPackageName().equals(r.getPackageName()));
}
/**
* <p>getInfo</p>
*
* @return a {@link java.lang.String} object.
*/
public String getInfo() {
return " Ready Runnable Discovery Link discoveryUsingBridge/discoveryUsingCdp/discoveryUsingRoutes/package: "
+ discoveryUsingBridge() + "/"
+ discoveryUsingCdp() + "/"
+ discoveryUsingRoutes() + "/"+ getPackageName();
}
/**
* <p>discoveryUsingBridge</p>
*
* @return a boolean.
*/
public boolean discoveryUsingBridge() {
return discoveryUsingBridge;
}
/**
* <p>Setter for the field <code>discoveryUsingBridge</code>.</p>
*
* @param discoveryUsingBridge a boolean.
*/
public void setDiscoveryUsingBridge(boolean discoveryUsingBridge) {
this.discoveryUsingBridge = discoveryUsingBridge;
}
/**
* <p>discoveryUsingCdp</p>
*
* @return a boolean.
*/
public boolean discoveryUsingCdp() {
return discoveryUsingCdp;
}
/**
* <p>Setter for the field <code>discoveryUsingCdp</code>.</p>
*
* @param discoveryUsingCdp a boolean.
*/
public void setDiscoveryUsingCdp(boolean discoveryUsingCdp) {
this.discoveryUsingCdp = discoveryUsingCdp;
}
/**
* <p>discoveryUsingRoutes</p>
*
* @return a boolean.
*/
public boolean discoveryUsingRoutes() {
return discoveryUsingRoutes;
}
/**
* <p>Setter for the field <code>discoveryUsingRoutes</code>.</p>
*
* @param discoveryUsingRoutes a boolean.
*/
public void setDiscoveryUsingRoutes(boolean discoveryUsingRoutes) {
this.discoveryUsingRoutes = discoveryUsingRoutes;
}
/**
* <p>Getter for the field <code>packageName</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getPackageName() {
return packageName;
}
/** {@inheritDoc} */
public void setPackageName(String packageName) {
this.packageName = packageName;
}
/**
* This method is useful to get forwarding table
* for switch failed.
*/
private void parseBridgeNodes() {
LogUtils.debugf(this, "parseBridgeNodes: searching bridge port for bridge identifier not yet already found. Iterating on bridge nodes.");
List<LinkableNode> bridgenodeschanged = new ArrayList<LinkableNode>();
for (LinkableNode curNode : m_bridgeNodes.values()) {
LogUtils.debugf(this, "parseBridgeNodes: parsing bridge: %d/%s", curNode.getNodeId(), curNode.getSnmpPrimaryIpAddr());
// get macs
final List<String> macs = getNotAlreadyFoundMacsOnNode(curNode);
if (macs.isEmpty()) continue;
SnmpAgentConfig agentConfig = null;
String className = null;
final LinkdConfig linkdConfig = m_linkd.getLinkdConfig();
linkdConfig.getReadLock().lock();
try {
boolean useVlan = linkdConfig.isVlanDiscoveryEnabled();
if (linkdConfig.getPackage(getPackageName()).hasEnableVlanDiscovery()) {
useVlan = linkdConfig.getPackage(getPackageName()).getEnableVlanDiscovery();
}
if (useVlan && linkdConfig.hasClassName(curNode.getSysoid())) {
className = linkdConfig.getVlanClassName(curNode.getSysoid());
}
final InetAddress addr = curNode.getSnmpPrimaryIpAddr();
if (addr == null) {
LogUtils.errorf(this, "parseBridgeNodes: Failed to load SNMP parameter from SNMP configuration file.");
return;
}
agentConfig = SnmpPeerFactory.getInstance().getAgentConfig(addr);
String community = agentConfig.getReadCommunity();
for (final String mac : macs) {
LogUtils.debugf(this, "parseBridgeNodes: parsing MAC: %s", mac);
if (className != null && (className.equals(CiscoVlanTable.class.getName())
|| className.equals(IntelVlanTable.class.getName()))){
for (OnmsVlan vlan : curNode.getVlans()) {
if (vlan.getVlanStatus() != VlanCollectorEntry.VLAN_STATUS_OPERATIONAL || vlan.getVlanType() != VlanCollectorEntry.VLAN_TYPE_ETHERNET) {
LogUtils.debugf(this, "parseBridgeNodes: skipping VLAN: %s", vlan.getVlanName());
continue;
}
agentConfig.setReadCommunity(community+"@"+vlan.getVlanId());
curNode = collectMacAddress(this, agentConfig, curNode, mac, vlan.getVlanId());
agentConfig.setReadCommunity(community);
}
} else {
int vlan = SnmpCollection.DEFAULT_VLAN_INDEX;
if (useVlan) vlan = SnmpCollection.TRUNK_VLAN_INDEX;
curNode = collectMacAddress(this, agentConfig, curNode, mac, vlan);
}
}
bridgenodeschanged.add(curNode);
} finally {
linkdConfig.getReadLock().unlock();
}
}
for (LinkableNode node : bridgenodeschanged) {
m_bridgeNodes.put(node.getNodeId(), node);
}
}
private static LinkableNode collectMacAddress(DiscoveryLink discoveryLink, SnmpAgentConfig agentConfig, LinkableNode node,String mac,int vlan) {
FdbTableGet coll = new FdbTableGet(agentConfig,mac);
LogUtils.debugf(discoveryLink, "collectMacAddress: finding entry in bridge forwarding table for MAC on node: %s/%d", mac, node.getNodeId());
int bridgeport = coll.getBridgePort();
if (bridgeport > 0 && coll.getBridgePortStatus() == QueryManager.SNMP_DOT1D_FDB_STATUS_LEARNED) {
node.addMacAddress(bridgeport, mac, Integer.toString(vlan));
LogUtils.debugf(discoveryLink, "collectMacAddress: found MAC on bridge port: %d", bridgeport);
} else {
bridgeport = coll.getQBridgePort();
if (bridgeport > 0 && coll.getQBridgePortStatus() == QueryManager.SNMP_DOT1D_FDB_STATUS_LEARNED) {
node.addMacAddress(bridgeport, mac, Integer.toString(vlan));
LogUtils.debugf(discoveryLink, "collectMacAddress: found MAC on bridge port: %d", bridgeport);
} else {
LogUtils.debugf(discoveryLink, "collectMacAddress: MAC not found: %d", bridgeport);
}
}
return node;
}
private List<String> getNotAlreadyFoundMacsOnNode(LinkableNode node){
LogUtils.debugf(this, "getNotAlreadyFoundMacsOnNode: Searching Not Yet Found Bridge Identifier Occurrence on Node: %d", node.getNodeId());
List<String> macs = new ArrayList<String>();
for (LinkableNode curNode : m_bridgeNodes.values()) {
if (node.getNodeId() == curNode.getNodeId()) continue;
for (String curMac : curNode.getBridgeIdentifiers()) {
if (node.hasMacAddress(curMac)) continue;
if (macs.contains(curMac)) continue;
LogUtils.debugf(this, "getNotAlreadyFoundMacsOnNode: Found a node/Bridge Identifier %d/%s that was not found in bridge forwarding table for bridge node: %d", curNode.getNodeId(), curMac, node.getNodeId());
macs.add(curMac);
}
}
LogUtils.debugf(this, "getNotAlreadyFoundMacsOnNode: Searching Not Yet Found MAC Address Occurrence on Node: %d", node.getNodeId());
for (String curMac : m_macToAtinterface.keySet()) {
if (node.hasMacAddress(curMac)) continue;
if (macs.contains(curMac)) continue;
LogUtils.debugf(this, "getNotAlreadyFoundMacsOnNode: Found a MAC Address %s that was not found in bridge forwarding table for bridge node: %d", curMac, node.getNodeId());
macs.add(curMac);
}
return macs;
}
/**
* <p>isEnableDownloadDiscovery</p>
*
* @return a boolean.
*/
public boolean isEnableDownloadDiscovery() {
return enableDownloadDiscovery;
}
/**
* <p>Setter for the field <code>enableDownloadDiscovery</code>.</p>
*
* @param enableDownloaddiscovery a boolean.
*/
public void setEnableDownloadDiscovery(boolean enableDownloaddiscovery) {
this.enableDownloadDiscovery = enableDownloaddiscovery;
}
/**
* <p>isForceIpRouteDiscoveryOnEtherNet</p>
*
* @return a boolean.
*/
public boolean isForceIpRouteDiscoveryOnEtherNet() {
return forceIpRouteDiscoveryOnEtherNet;
}
/**
* <p>Setter for the field <code>forceIpRouteDiscoveryOnEtherNet</code>.</p>
*
* @param forceIpRouteDiscoveryOnEtherNet a boolean.
*/
public void setForceIpRouteDiscoveryOnEtherNet(
boolean forceIpRouteDiscoveryOnEtherNet) {
this.forceIpRouteDiscoveryOnEtherNet = forceIpRouteDiscoveryOnEtherNet;
}
}