X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fhosttracker%2Fimplementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fhosttracker%2Finternal%2FHostTracker.java;h=e4704d30489b2a212538ebc1d1503a95b4064784;hp=3ff474732fe01628996d0c8685b04910080b26e3;hb=c97615f9dcd902079b828eebaafb420a0de61193;hpb=c5630f2945eb5370f9829514ef72de41d41eb2be diff --git a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java index 3ff474732f..e4704d3048 100644 --- a/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java +++ b/opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java @@ -29,6 +29,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.apache.felix.dm.Component; +import org.eclipse.osgi.framework.console.CommandInterpreter; +import org.eclipse.osgi.framework.console.CommandProvider; import org.opendaylight.controller.clustering.services.CacheConfigException; import org.opendaylight.controller.clustering.services.CacheExistException; import org.opendaylight.controller.clustering.services.ICacheUpdateAware; @@ -63,6 +65,8 @@ import org.opendaylight.controller.switchmanager.ISwitchManagerAware; import org.opendaylight.controller.switchmanager.Subnet; import org.opendaylight.controller.topologymanager.ITopologyManager; import org.opendaylight.controller.topologymanager.ITopologyManagerAware; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,12 +84,12 @@ import org.slf4j.LoggerFactory; */ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAware, IInventoryListener, - ITopologyManagerAware, ICacheUpdateAware { - static final String ACTIVE_HOST_CACHE = "hostTrackerAH"; - static final String INACTIVE_HOST_CACHE = "hostTrackerIH"; + ITopologyManagerAware, ICacheUpdateAware, CommandProvider { + static final String ACTIVE_HOST_CACHE = "hosttracker.ActiveHosts"; + static final String INACTIVE_HOST_CACHE = "hosttracker.InactiveHosts"; private static final Logger logger = LoggerFactory.getLogger(HostTracker.class); - private IHostFinder hostFinder; - private ConcurrentMap hostsDB; + protected IHostFinder hostFinder; + protected ConcurrentMap hostsDB; /* * Following is a list of hosts which have been requested by NB APIs to be * added, but either the switch or the port is not sup, so they will be @@ -95,12 +99,13 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw private final Set newHostNotify = Collections.synchronizedSet(new HashSet()); private ITopologyManager topologyManager; - private IClusterContainerServices clusterContainerService = null; - private ISwitchManager switchManager = null; + protected IClusterContainerServices clusterContainerService = null; + protected ISwitchManager switchManager = null; private Timer timer; private Timer arpRefreshTimer; private String containerName = null; private ExecutorService executor; + protected boolean stopping; private static class ARPPending { protected InetAddress hostIP; protected short sent_count; @@ -133,7 +138,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw // This list contains the hosts for which ARP requests are being sent // periodically - private final List ARPPendingList = new ArrayList(); + ConcurrentMap ARPPendingList; /* * This list below contains the hosts which were initially in ARPPendingList * above, but ARP response didn't come from there hosts after multiple @@ -150,14 +155,16 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * * We can't recover from condition 3 above */ - private final List failedARPReqList = new ArrayList(); + ConcurrentMap failedARPReqList; public HostTracker() { } private void startUp() { + nonClusterObjectCreate(); allocateCache(); retrieveCache(); + stopping = false; timer = new Timer(); timer.schedule(new OutStandingARPHandler(), 4000, 4000); @@ -168,7 +175,6 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.debug("startUp: Caches created, timers started"); } - @SuppressWarnings("deprecation") private void allocateCache() { if (this.clusterContainerService == null) { logger.error("un-initialized clusterContainerService, can't create cache"); @@ -177,9 +183,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.debug("Creating Cache for HostTracker"); try { this.clusterContainerService.createCache(ACTIVE_HOST_CACHE, - EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); this.clusterContainerService.createCache(INACTIVE_HOST_CACHE, - EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); } catch (CacheConfigException cce) { logger.error("Cache couldn't be created for HostTracker - check cache mode"); } catch (CacheExistException cce) { @@ -188,7 +194,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.debug("Cache successfully created for HostTracker"); } - @SuppressWarnings({ "unchecked", "deprecation" }) + @SuppressWarnings({ "unchecked" }) private void retrieveCache() { if (this.clusterContainerService == null) { logger.error("un-initialized clusterContainerService, can't retrieve cache"); @@ -213,9 +219,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw public void nonClusterObjectCreate() { hostsDB = new ConcurrentHashMap(); inactiveStaticHosts = new ConcurrentHashMap(); + ARPPendingList = new ConcurrentHashMap(); + failedARPReqList = new ConcurrentHashMap(); } - public void shutDown() { } @@ -329,7 +336,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw /* Add this host to ARPPending List for any potential retries */ - AddtoARPPendingList(networkAddress); + addToARPPendingList(networkAddress); logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...", networkAddress.getHostAddress()); @@ -373,31 +380,19 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw return list; } - private void AddtoARPPendingList(InetAddress networkAddr) { + private void addToARPPendingList(InetAddress networkAddr) { ARPPending arphost = new ARPPending(); arphost.setHostIP(networkAddr); arphost.setSent_count((short) 1); - ARPPendingList.add(arphost); + ARPPendingList.put(networkAddr, arphost); logger.debug("Host Added to ARPPending List, IP: {}", networkAddr); } - private void removePendingARPFromList(int index) { - if (index >= ARPPendingList.size()) { - logger.warn("removePendingARPFromList(): index greater than the List. Size:{}, Index:{}", - ARPPendingList.size(), index); - return; - } - ARPPending arphost = ARPPendingList.remove(index); - HostTrackerCallable htCallable = arphost.getHostTrackerCallable(); - if (htCallable != null) - htCallable.wakeup(); - } - public void setCallableOnPendingARP(InetAddress networkAddr, HostTrackerCallable callable) { ARPPending arphost; - for (int i = 0; i < ARPPendingList.size(); i++) { - arphost = ARPPendingList.get(i); + for (Entry entry : ARPPendingList.entrySet()) { + arphost = entry.getValue(); if (arphost.getHostIP().equals(networkAddr)) { arphost.setHostTrackerCallable(callable); } @@ -407,34 +402,23 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw private void processPendingARPReqs(InetAddress networkAddr) { ARPPending arphost; - for (int i = 0; i < ARPPendingList.size(); i++) { - arphost = ARPPendingList.get(i); - if (arphost.getHostIP().equals(networkAddr)) { - /* - * An ARP was sent for this host. The address is learned, remove - * the request - */ - removePendingARPFromList(i); - logger.debug("Host Removed from ARPPending List, IP: {}", networkAddr); - return; + if ((arphost = ARPPendingList.remove(networkAddr)) != null) { + // Remove the arphost from ARPPendingList as it has been learned now + logger.debug("Host Removed from ARPPending List, IP: {}", networkAddr); + HostTrackerCallable htCallable = arphost.getHostTrackerCallable(); + if (htCallable != null) { + htCallable.wakeup(); } + return; } /* * It could have been a host from the FailedARPReqList */ - for (int i = 0; i < failedARPReqList.size(); i++) { - arphost = failedARPReqList.get(i); - if (arphost.getHostIP().equals(networkAddr)) { - /* - * An ARP was sent for this host. The address is learned, remove - * the request - */ - failedARPReqList.remove(i); - logger.debug("Host Removed from FailedARPReqList List, IP: {}", networkAddr); - return; - } + if (failedARPReqList.containsKey(networkAddr)) { + failedARPReqList.remove(networkAddr); + logger.debug("Host Removed from FailedARPReqList List, IP: {}", networkAddr); } } @@ -452,7 +436,15 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } private void replaceHost(InetAddress networkAddr, HostNodeConnector removedHost, HostNodeConnector newHost) { + // Ignore ARP messages from internal nodes + NodeConnector newHostNc = newHost.getnodeConnector(); + boolean newHostIsInternal = topologyManager.isInternal(newHostNc); + if (newHostIsInternal) { + return; + } + newHost.initArpSendCountDown(); + if (hostsDB.replace(networkAddr, removedHost, newHost)) { logger.debug("Host move occurred: Old Host IP:{}, New Host IP: {}", removedHost.getNetworkAddress() .getHostAddress(), newHost.getNetworkAddress().getHostAddress()); @@ -513,14 +505,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw replaceHost(networkAddr, removedHost, host); return; } else { - logger.error("Host to be removed not found in hostsDB. Host {}", removedHost); + logger.error("Host to be removed not found in hostsDB"); } } - if (removedHost == null) { - // It is a new host - learnNewHost(host); - } + // It is a new host + learnNewHost(host); /* check if there is an outstanding request for this host */ processPendingARPReqs(networkAddr); @@ -536,6 +526,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw if (hostExists(host)) { HostNodeConnector existinghost = hostsDB.get(host.getNetworkAddress()); existinghost.initArpSendCountDown(); + // Update the host + hostsDB.put(host.getNetworkAddress(), existinghost); return; } new NotifyHostThread(host).start(); @@ -610,6 +602,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * @param currentTier * The Tier on which n belongs */ + @SuppressWarnings("unused") private void updateSwitchTiers(Node n, int currentTier) { Map> ndlinks = topologyManager.getNodeEdges(); if (ndlinks == null) { @@ -671,12 +664,14 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } // This is the case where Tier was never set for this node Tier t = (Tier) switchManager.getNodeProp(n, Tier.TierPropName); - if (t == null) + if (t == null) { return true; - if (t.getValue() == 0) + } + if (t.getValue() == 0) { return true; - else if (t.getValue() > tier) + } else if (t.getValue() > tier) { return true; + } return false; } @@ -685,6 +680,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * cleanup is performed during cases such as Topology Change where the * existing Tier values might become incorrect */ + @SuppressWarnings("unused") private void clearTiers() { Set nodes = null; if (switchManager == null) { @@ -731,8 +727,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw @Override public List> getHostNetworkHierarchy(InetAddress hostAddress) { HostNodeConnector host = hostQuery(hostAddress); - if (host == null) + if (host == null) { return null; + } List> hierarchies = new ArrayList>(); ArrayList currHierarchy = new ArrayList(); @@ -760,10 +757,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw int result = 0; for (int i = 0; i < hex.length(); i++) { result = (int) ((dpid >> (i * 8)) & 0xff); - if (result == 0) + if (result == 0) { continue; - if (result < 0x30) + } + if (result < 0x30) { result += 0x40; + } sb.append(String.format("%c", result)); } return sb.reverse().toString(); @@ -784,10 +783,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw private void updateCurrentHierarchy(Node node, ArrayList currHierarchy, List> fullHierarchy) { // currHierarchy.add(String.format("%x", currSw.getId())); currHierarchy.add(dpidToHostNameHack((Long) node.getID())); - ArrayList currHierarchyClone = (ArrayList) currHierarchy.clone(); // Shallow - // copy - // as - // required + // Shallow copy as required + ArrayList currHierarchyClone = (ArrayList) currHierarchy.clone(); Map> ndlinks = topologyManager.getNodeEdges(); if (ndlinks == null) { @@ -809,14 +806,27 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw Node dstNode = lt.getHeadNodeConnector().getNode(); Tier nodeTier = (Tier) switchManager.getNodeProp(node, Tier.TierPropName); + /* + * If the host is directly attached to the src node, then the node + * should have been assigned the "Access" tier in + * notifyHostLearnedOrRemoved. If not, it would be assigned + * "Unknown" tier. Thus the tier of host attached node cannot be + * null. If the src node here, is the next node in the hierarchy of + * the nodes, then its tier cannot be null + */ + Tier dstNodeTier = (Tier) switchManager.getNodeProp(dstNode, Tier.TierPropName); + /* + * Skip if the tier of the destination node is null + */ + if (dstNodeTier == null) { + continue; + } if (dstNodeTier.getValue() > nodeTier.getValue()) { ArrayList buildHierarchy = currHierarchy; if (currHierarchy.size() > currHierarchyClone.size()) { - buildHierarchy = (ArrayList) currHierarchyClone.clone(); // Shallow - // copy - // as - // required + // Shallow copy as required + buildHierarchy = (ArrayList) currHierarchyClone.clone(); fullHierarchy.add(buildHierarchy); } updateCurrentHierarchy(dstNode, buildHierarchy, fullHierarchy); @@ -899,15 +909,15 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw public void subnetNotify(Subnet sub, boolean add) { logger.debug("Received subnet notification: {} add={}", sub, add); if (add) { - for (int i = 0; i < failedARPReqList.size(); i++) { + for (Entry entry : failedARPReqList.entrySet()) { ARPPending arphost; - arphost = failedARPReqList.get(i); + arphost = entry.getValue(); if (hostFinder == null) { logger.warn("ARPHandler Services are not available on subnet addition"); continue; } - logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress()); - hostFinder.find(arphost.getHostIP()); + logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress()); + hostFinder.find(arphost.getHostIP()); } } } @@ -915,15 +925,29 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw class OutStandingARPHandler extends TimerTask { @Override public void run() { + if (stopping) { + return; + } ARPPending arphost; /* This routine runs every 4 seconds */ - for (int i = 0; i < ARPPendingList.size(); i++) { - arphost = ARPPendingList.get(i); + logger.trace("Number of Entries in ARP Pending/Failed Lists: ARPPendingList = {}, failedARPReqList = {}", + ARPPendingList.size(), failedARPReqList.size()); + for (Entry entry : ARPPendingList.entrySet()) { + arphost = entry.getValue(); + + if (hostsDB.containsKey(arphost.getHostIP())) { + // this host is already learned, shouldn't be in + // ARPPendingList + // Remove it and continue + logger.warn("Learned Host {} found in ARPPendingList", arphost.getHostIP()); + ARPPendingList.remove(entry.getKey()); + continue; + } if (arphost.getSent_count() < switchManager.getHostRetryCount()) { /* * No reply has been received of first ARP Req, send the - * next one. Before sending the ARP, check if ARPHandler - * is available or not + * next one. Before sending the ARP, check if ARPHandler is + * available or not */ if (hostFinder == null) { logger.warn("ARPHandler Services are not available for Outstanding ARPs"); @@ -934,10 +958,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.debug("ARP Sent from ARPPending List, IP: {}", arphost.getHostIP().getHostAddress()); } else if (arphost.getSent_count() >= switchManager.getHostRetryCount()) { /* - * ARP requests have been sent without receiving a - * reply, remove this from the pending list + * ARP requests have been sent without receiving a reply, + * remove this from the pending list */ - removePendingARPFromList(i); + ARPPendingList.remove(entry.getKey()); logger.debug("ARP reply not received after multiple attempts, removing from Pending List IP: {}", arphost.getHostIP().getHostAddress()); /* @@ -945,10 +969,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * on link up events */ logger.debug("Adding the host to FailedARPReqList IP: {}", arphost.getHostIP().getHostAddress()); - failedARPReqList.add(arphost); + failedARPReqList.put(entry.getKey(), arphost); } else { - logger.error("Inavlid arp_sent count for entry at index: {}", i); + logger.error("Inavlid arp_sent count for entry: {}", entry); } } } @@ -956,8 +980,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw private class ARPRefreshHandler extends TimerTask { @Override - @SuppressWarnings("deprecation") public void run() { + if (stopping) { + return; + } if ((clusterContainerService != null) && !clusterContainerService.amICoordinator()) { return; } @@ -1075,6 +1101,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw */ if (switchManager.isNodeConnectorEnabled(nc)) { learnNewHost(host); + processPendingARPReqs(networkAddr); notifyHostLearnedOrRemoved(host, true); } else { inactiveStaticHosts.put(nc, host); @@ -1209,8 +1236,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw @Override public void notifyNode(Node node, UpdateType type, Map propMap) { - if (node == null) + if (node == null) { return; + } switch (type) { case REMOVED: @@ -1231,8 +1259,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw @Override public void notifyNodeConnector(NodeConnector nodeConnector, UpdateType type, Map propMap) { - if (nodeConnector == null) + if (nodeConnector == null) { return; + } boolean up = false; switch (type) { @@ -1286,11 +1315,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw private void handleNodeConnectorStatusUp(NodeConnector nodeConnector) { ARPPending arphost; + HostNodeConnector host = null; logger.debug("handleNodeConnectorStatusUp {}", nodeConnector); - for (int i = 0; i < failedARPReqList.size(); i++) { - arphost = failedARPReqList.get(i); + for (Entry entry : failedARPReqList.entrySet()) { + arphost = entry.getValue(); logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress()); if (hostFinder == null) { logger.warn("ARPHandler is not available at interface up"); @@ -1298,12 +1328,26 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw nodeConnector); continue; } - hostFinder.find(arphost.getHostIP()); + + // Send a broadcast ARP only on the interface which just came up. + // Use hostFinder's "probe" method + try { + byte[] dataLayerAddress = NetUtils.getBroadcastMACAddr(); + host = new HostNodeConnector(dataLayerAddress, arphost.getHostIP(), nodeConnector, (short) 0); + hostFinder.probe(host); + } catch (ConstructionException e) { + logger.debug("HostNodeConnector couldn't be created for Host: {}, NodeConnector: {}", + arphost.getHostIP(), nodeConnector); + logger.error("", e); + } + logger.debug("Done. handleNodeConnectorStatusUp {}", nodeConnector); } - HostNodeConnector host = inactiveStaticHosts.get(nodeConnector); + + host = inactiveStaticHosts.get(nodeConnector); if (host != null) { inactiveStaticHosts.remove(nodeConnector); learnNewHost(host); + processPendingARPReqs(host.getNetworkAddress()); notifyHostLearnedOrRemoved(host, true); } } @@ -1346,8 +1390,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } public String getContainerName() { - if (containerName == null) + if (containerName == null) { return GlobalConstants.DEFAULT.toString(); + } return containerName; } @@ -1383,6 +1428,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * */ void start() { + registerWithOSGIConsole(); } /** @@ -1391,42 +1437,65 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * calls * */ - void stop(){ + void stop() { } void stopping() { + stopping = true; arpRefreshTimer.cancel(); timer.cancel(); - executor.shutdown(); + executor.shutdownNow(); } @Override public void edgeOverUtilized(Edge edge) { - // TODO Auto-generated method stub } @Override public void edgeUtilBackToNormal(Edge edge) { - // TODO Auto-generated method stub } @Override - public void entryCreated(InetAddress key, String cacheName, - boolean originLocal) { - if (originLocal) return; + public void entryCreated(InetAddress key, String cacheName, boolean originLocal) { + if (originLocal) { + return; + } processPendingARPReqs(key); } @Override - public void entryUpdated(InetAddress key, HostNodeConnector new_value, - String cacheName, boolean originLocal) { + public void entryUpdated(InetAddress key, HostNodeConnector new_value, String cacheName, boolean originLocal) { + } + + @Override + public void entryDeleted(InetAddress key, String cacheName, boolean originLocal) { + } + + private void registerWithOSGIConsole() { + BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); + bundleContext.registerService(CommandProvider.class.getName(), this, null); } @Override - public void entryDeleted(InetAddress key, String cacheName, - boolean originLocal) { + public String getHelp() { + return null; + } + + public void _dumpPendingARPReqList(CommandInterpreter ci) { + ARPPending arphost; + for (Entry entry : ARPPendingList.entrySet()) { + arphost = entry.getValue(); + ci.println(arphost.getHostIP().toString()); + } } + public void _dumpFailedARPReqList(CommandInterpreter ci) { + ARPPending arphost; + for (Entry entry : failedARPReqList.entrySet()) { + arphost = entry.getValue(); + ci.println(arphost.getHostIP().toString()); + } + } }