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=f728b35bbfa7f492c3937b87616e4b655ba3f16f;hp=2fd81cbcd7b652e604f63c8f691a16b7dd29b185;hb=475d28f717bae92b2cc10b0589131771fcc62242;hpb=6e28a7e7bb41088e8a7492523e61ed7b90bff4c2 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 2fd81cbcd7..f728b35bbf 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 @@ -24,6 +24,7 @@ import java.util.TimerTask; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -36,6 +37,11 @@ import org.opendaylight.controller.clustering.services.CacheExistException; import org.opendaylight.controller.clustering.services.ICacheUpdateAware; import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.hosttracker.HostIdFactory; +import org.opendaylight.controller.hosttracker.IHostId; +import org.opendaylight.controller.hosttracker.IHostTrackerShell; +import org.opendaylight.controller.hosttracker.IPHostId; +import org.opendaylight.controller.hosttracker.IPMacHostId; import org.opendaylight.controller.hosttracker.IfHostListener; import org.opendaylight.controller.hosttracker.IfIptoHost; import org.opendaylight.controller.hosttracker.IfNewHostNotify; @@ -83,13 +89,25 @@ import org.slf4j.LoggerFactory; * removed the database */ -public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAware, IInventoryListener, - ITopologyManagerAware, ICacheUpdateAware, CommandProvider { +/*** + * + * HostTracker db key scheme implementation support. Support has been added for + * IP only or IP + MAC scheme as of now. User can use either of the schemes + * based on the configuration done in config.ini file. By default IP only key + * scheme is choosen. The attribute to be set in config.ini is + * hosttracker.keyscheme. It could have a value of 0 or 1 as of now. 0 is for IP + * only scheme. 1 is for IP + MAC scheme. + * + * + */ + +public class HostTracker implements IfIptoHost, IfHostListener, IHostTrackerShell, ISwitchManagerAware, IInventoryListener, + 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 final Set hostFinders = new CopyOnWriteArraySet(); + 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 @@ -99,19 +117,24 @@ 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 boolean hostRefresh = true; + private static int hostRetryCount = 5; + private String keyScheme = null; + private static class ARPPending { - protected InetAddress hostIP; + protected IHostId hostId; protected short sent_count; protected HostTrackerCallable hostTrackerCallable; - public InetAddress getHostIP() { - return hostIP; + public IHostId getHostId() { + return hostId; } public short getSent_count() { @@ -122,8 +145,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw return hostTrackerCallable; } - public void setHostIP(InetAddress networkAddr) { - this.hostIP = networkAddr; + public void setHostId(IHostId id) { + this.hostId = id; } public void setSent_count(short count) { @@ -134,9 +157,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw hostTrackerCallable = callable; } } + // This list contains the hosts for which ARP requests are being sent // periodically - ConcurrentMap ARPPendingList; + 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 @@ -153,7 +177,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * * We can't recover from condition 3 above */ - ConcurrentMap failedARPReqList; + ConcurrentMap failedARPReqList; public HostTracker() { } @@ -162,6 +186,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw nonClusterObjectCreate(); allocateCache(); retrieveCache(); + stopping = false; timer = new Timer(); timer.schedule(new OutStandingARPHandler(), 4000, 4000); @@ -169,10 +194,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw /* ARP Refresh Timer to go off every 5 seconds to implement ARP aging */ arpRefreshTimer = new Timer(); arpRefreshTimer.schedule(new ARPRefreshHandler(), 5000, 5000); + keyScheme = HostIdFactory.getScheme(); 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"); @@ -192,15 +217,14 @@ 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"); return; } logger.debug("Retrieving cache for HostTrackerAH"); - hostsDB = (ConcurrentMap) this.clusterContainerService - .getCache(ACTIVE_HOST_CACHE); + hostsDB = (ConcurrentMap) this.clusterContainerService.getCache(ACTIVE_HOST_CACHE); if (hostsDB == null) { logger.error("Cache couldn't be retrieved for HostTracker"); } @@ -215,13 +239,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } public void nonClusterObjectCreate() { - hostsDB = new ConcurrentHashMap(); + hostsDB = new ConcurrentHashMap(); inactiveStaticHosts = new ConcurrentHashMap(); - ARPPendingList = new ConcurrentHashMap(); - failedARPReqList = new ConcurrentHashMap(); + ARPPendingList = new ConcurrentHashMap(); + failedARPReqList = new ConcurrentHashMap(); } - public void shutDown() { } @@ -234,14 +257,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } public void setArpHandler(IHostFinder hostFinder) { - this.hostFinder = hostFinder; + this.hostFinders.add(hostFinder); } public void unsetArpHandler(IHostFinder hostFinder) { - if (this.hostFinder == hostFinder) { - logger.debug("Arp Handler Service removed!"); - this.hostFinder = null; - } + logger.debug("Arp Handler Service removed!"); + this.hostFinders.remove(hostFinder); } public void setTopologyManager(ITopologyManager s) { @@ -256,157 +277,156 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } private boolean hostExists(HostNodeConnector host) { - HostNodeConnector lhost = hostsDB.get(host.getNetworkAddress()); + IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress()); + HostNodeConnector lhost = hostsDB.get(id); return host.equals(lhost); } - private HostNodeConnector getHostFromOnActiveDB(InetAddress networkAddress) { - return hostsDB.get(networkAddress); + private HostNodeConnector getHostFromOnActiveDB(IHostId id) { + return hostsDB.get(id); } - private Entry getHostFromInactiveDB(InetAddress networkAddress) { + private Entry getHostFromInactiveDB(IHostId id) { for (Entry entry : inactiveStaticHosts.entrySet()) { - if (entry.getValue().equalsByIP(networkAddress)) { - logger.debug("getHostFromInactiveDB(): Inactive Host found for IP:{} ", networkAddress.getHostAddress()); + HostNodeConnector hnc = entry.getValue(); + IHostId cmpId = HostIdFactory.create(hnc.getNetworkAddress(), hnc.getDataLayerAddress()); + if (cmpId.equals(id)) { + logger.debug("getHostFromInactiveDB(): Inactive Host found for ID:{} ", decodeIPFromId(id)); return entry; } } - logger.debug("getHostFromInactiveDB() Inactive Host Not found for IP: {}", networkAddress.getHostAddress()); + logger.debug("getHostFromInactiveDB() Inactive Host Not found for ID: {}", decodeIPFromId(id)); return null; } - private void removeHostFromInactiveDB(InetAddress networkAddress) { + private void removeHostFromInactiveDB(IHostId id) { NodeConnector nodeConnector = null; for (Entry entry : inactiveStaticHosts.entrySet()) { - if (entry.getValue().equalsByIP(networkAddress)) { + HostNodeConnector hnc = entry.getValue(); + IHostId cmpId = HostIdFactory.create(hnc.getNetworkAddress(), hnc.getDataLayerAddress()); + if (cmpId.equals(id)) { nodeConnector = entry.getKey(); break; } } if (nodeConnector != null) { inactiveStaticHosts.remove(nodeConnector); - logger.debug("removeHostFromInactiveDB(): Host Removed for IP: {}", networkAddress.getHostAddress()); + logger.debug("removeHostFromInactiveDB(): Host Removed for IP: {}", decodeIPFromId(id)); return; } - logger.debug("removeHostFromInactiveDB(): Host Not found for IP: {}", networkAddress.getHostAddress()); + logger.debug("removeHostFromInactiveDB(): Host Not found for IP: {}", decodeIPFromId(id)); } protected boolean hostMoved(HostNodeConnector host) { - if (hostQuery(host.getNetworkAddress()) != null) { + IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress()); + if (hostQuery(id) != null) { return true; } return false; } @Override - public HostNodeConnector hostQuery(InetAddress networkAddress) { - return hostsDB.get(networkAddress); + public HostNodeConnector hostQuery(IHostId id) { + return hostsDB.get(id); } @Override - public Future discoverHost(InetAddress networkAddress) { + public Future discoverHost(IHostId id) { if (executor == null) { - logger.error("discoverHost: Null executor"); + logger.debug("discoverHost: Null executor"); return null; } - Callable worker = new HostTrackerCallable(this, networkAddress); + Callable worker = new HostTrackerCallable(this, id); Future submit = executor.submit(worker); return submit; } @Override - public HostNodeConnector hostFind(InetAddress networkAddress) { + public HostNodeConnector hostFind(IHostId id) { /* * Sometimes at boot with containers configured in the startup we hit * this path (from TIF) when hostFinder has not been set yet Caller * already handles the null return */ - if (hostFinder == null) { - logger.debug("Exiting hostFind, null hostFinder"); + if (hostFinders.isEmpty()) { + logger.debug("No available host finders, exiting hostFind()"); return null; } - HostNodeConnector host = hostQuery(networkAddress); + HostNodeConnector host = hostQuery(id); if (host != null) { - logger.debug("hostFind(): Host found for IP: {}", networkAddress.getHostAddress()); + logger.debug("hostFind(): Host found for IP: {}", id); return host; } /* Add this host to ARPPending List for any potential retries */ - AddtoARPPendingList(networkAddress); - logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...", - networkAddress.getHostAddress()); + addToARPPendingList(id); + logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...", id); /* host is not found, initiate a discovery */ - - hostFinder.find(networkAddress); + for (IHostFinder hf : hostFinders) { + InetAddress addr = decodeIPFromId(id); + hf.find(addr); + } return null; } @Override public Set getAllHosts() { - Set allHosts = new HashSet(); - for (Entry entry : hostsDB.entrySet()) { - HostNodeConnector host = entry.getValue(); - allHosts.add(host); - } - logger.debug("Exiting getAllHosts, Found {} Hosts", allHosts.size()); + Set allHosts = new HashSet(hostsDB.values()); return allHosts; } @Override public Set getActiveStaticHosts() { Set list = new HashSet(); - for (Entry entry : hostsDB.entrySet()) { + for (Entry entry : hostsDB.entrySet()) { HostNodeConnector host = entry.getValue(); if (host.isStaticHost()) { list.add(host); } } - logger.debug("getActiveStaticHosts(): Found {} Hosts", list.size()); return list; } @Override public Set getInactiveStaticHosts() { - Set list = new HashSet(); - for (Entry entry : inactiveStaticHosts.entrySet()) { - list.add(entry.getValue()); - } - logger.debug("getInactiveStaticHosts(): Found {} Hosts", list.size()); + Set list = new HashSet(inactiveStaticHosts.values()); return list; } - private void AddtoARPPendingList(InetAddress networkAddr) { + private void addToARPPendingList(IHostId id) { ARPPending arphost = new ARPPending(); - arphost.setHostIP(networkAddr); + arphost.setHostId(id); arphost.setSent_count((short) 1); - ARPPendingList.put(networkAddr, arphost); - logger.debug("Host Added to ARPPending List, IP: {}", networkAddr); + ARPPendingList.put(id, arphost); + logger.debug("Host Added to ARPPending List, IP: {}", decodeIPFromId(id)); + } - public void setCallableOnPendingARP(InetAddress networkAddr, HostTrackerCallable callable) { + public void setCallableOnPendingARP(IHostId id, HostTrackerCallable callable) { ARPPending arphost; - for (Entry entry : ARPPendingList.entrySet()) { + for (Entry entry : ARPPendingList.entrySet()) { arphost = entry.getValue(); - if (arphost.getHostIP().equals(networkAddr)) { + if (arphost.getHostId().equals(id)) { arphost.setHostTrackerCallable(callable); } } } - private void processPendingARPReqs(InetAddress networkAddr) { + private void processPendingARPReqs(IHostId id) { ARPPending arphost; - if ((arphost = ARPPendingList.remove(networkAddr)) != null) { + if ((arphost = ARPPendingList.remove(id)) != null) { // Remove the arphost from ARPPendingList as it has been learned now - logger.debug("Host Removed from ARPPending List, IP: {}", networkAddr); + logger.debug("Host Removed from ARPPending List, IP: {}", id); HostTrackerCallable htCallable = arphost.getHostTrackerCallable(); - if (htCallable != null) + if (htCallable != null) { htCallable.wakeup(); + } return; } @@ -414,26 +434,27 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * It could have been a host from the FailedARPReqList */ - if (failedARPReqList.containsKey(networkAddr)) { - failedARPReqList.remove(networkAddr); - logger.debug("Host Removed from FailedARPReqList List, IP: {}", networkAddr); + if (failedARPReqList.containsKey(id)) { + failedARPReqList.remove(id); + logger.debug("Host Removed from FailedARPReqList List, IP: {}", decodeIPFromId(id)); } } // Learn a new Host private void learnNewHost(HostNodeConnector host) { + IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress()); host.initArpSendCountDown(); - HostNodeConnector rHost = hostsDB.putIfAbsent(host.getNetworkAddress(), host); + HostNodeConnector rHost = hostsDB.putIfAbsent(id, host); if (rHost != null) { // Another host is already learned for this IP address, replace it - replaceHost(host.getNetworkAddress(), rHost, host); + replaceHost(id, rHost, host); } else { logger.debug("New Host Learned: MAC: {} IP: {}", HexEncode.bytesToHexString(host .getDataLayerAddressBytes()), host.getNetworkAddress().getHostAddress()); } } - private void replaceHost(InetAddress networkAddr, HostNodeConnector removedHost, HostNodeConnector newHost) { + private void replaceHost(IHostId id, HostNodeConnector removedHost, HostNodeConnector newHost) { // Ignore ARP messages from internal nodes NodeConnector newHostNc = newHost.getnodeConnector(); boolean newHostIsInternal = topologyManager.isInternal(newHostNc); @@ -443,7 +464,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw newHost.initArpSendCountDown(); - if (hostsDB.replace(networkAddr, removedHost, newHost)) { + if (hostsDB.replace(id, removedHost, newHost)) { logger.debug("Host move occurred: Old Host IP:{}, New Host IP: {}", removedHost.getNetworkAddress() .getHostAddress(), newHost.getNetworkAddress().getHostAddress()); logger.debug("Old Host MAC: {}, New Host MAC: {}", @@ -455,25 +476,25 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw /* * Host replacement has failed, do the recovery */ - hostsDB.put(networkAddr, newHost); - logger.error("Host replacement failed. Overwrite the host. Repalced Host: {}, New Host: {}", removedHost, + hostsDB.put(id, newHost); + logger.error("Host replacement failed. Overwrite the host. Replaced Host: {}, New Host: {}", removedHost, newHost); } notifyHostLearnedOrRemoved(removedHost, false); notifyHostLearnedOrRemoved(newHost, true); if (!newHost.isStaticHost()) { - processPendingARPReqs(networkAddr); + processPendingARPReqs(id); } } // Remove known Host - private void removeKnownHost(InetAddress key) { + private void removeKnownHost(IHostId key) { HostNodeConnector host = hostsDB.get(key); if (host != null) { logger.debug("Removing Host: IP:{}", host.getNetworkAddress().getHostAddress()); hostsDB.remove(key); } else { - logger.error("removeKnownHost(): Host for IP address {} not found in hostsDB", key.getHostAddress()); + logger.error("removeKnownHost(): Host for IP address {} not found in hostsDB", decodeIPFromId(key)); } } @@ -489,7 +510,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw public void run() { HostNodeConnector removedHost = null; InetAddress networkAddr = host.getNetworkAddress(); - + IHostId id = HostIdFactory.create(networkAddr, host.getDataLayerAddress()); /* Check for Host Move case */ if (hostMoved(host)) { /* @@ -498,36 +519,37 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * location parameters with new information, and notify the * applications listening to host move. */ - removedHost = hostsDB.get(networkAddr); + + removedHost = hostsDB.get(id); if (removedHost != null) { - replaceHost(networkAddr, removedHost, host); + replaceHost(id, 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); + processPendingARPReqs(id); notifyHostLearnedOrRemoved(host, true); } } @Override public void hostListener(HostNodeConnector host) { - - logger.debug("ARP received for Host: IP {}, MAC {}, {}", host.getNetworkAddress().getHostAddress(), + logger.debug("Received for Host: IP {}, MAC {}, {}", host.getNetworkAddress().getHostAddress(), HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host); if (hostExists(host)) { - HostNodeConnector existinghost = hostsDB.get(host.getNetworkAddress()); + IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress()); + HostNodeConnector existinghost = hostsDB.get(id); existinghost.initArpSendCountDown(); // Update the host - hostsDB.put(host.getNetworkAddress(), existinghost); + + hostsDB.put(id, existinghost); + logger.debug("hostListener returned without adding the host"); return; } new NotifyHostThread(host).start(); @@ -549,7 +571,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw ta.notifyHTClientHostRemoved(host); } } catch (Exception e) { - logger.error("Exception on callback", e); + logger.error("Exception on new host notification", e); } } } @@ -602,6 +624,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) { @@ -663,12 +686,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; } @@ -677,6 +702,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) { @@ -700,9 +726,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw int num = 1; for (ArrayList hierarchy : hierarchies) { StringBuffer buf = new StringBuffer(); - buf.append("Hierarchy#" + num + " : "); + buf.append("Hierarchy#").append(num).append(" : "); for (String switchName : hierarchy) { - buf.append(switchName + "/"); + buf.append(switchName).append("/"); } logger.debug("{} -> {}", getContainerName(), buf); num++; @@ -721,10 +747,11 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * Switch-Ids as String). */ @Override - public List> getHostNetworkHierarchy(InetAddress hostAddress) { - HostNodeConnector host = hostQuery(hostAddress); - if (host == null) + public List> getHostNetworkHierarchy(IHostId id) { + HostNodeConnector host = hostQuery(id); + if (host == null) { return null; + } List> hierarchies = new ArrayList>(); ArrayList currHierarchy = new ArrayList(); @@ -752,10 +779,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(); @@ -774,7 +803,6 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw */ @SuppressWarnings("unchecked") private void updateCurrentHierarchy(Node node, ArrayList currHierarchy, List> fullHierarchy) { - // currHierarchy.add(String.format("%x", currSw.getId())); currHierarchy.add(dpidToHostNameHack((Long) node.getID())); // Shallow copy as required ArrayList currHierarchyClone = (ArrayList) currHierarchy.clone(); @@ -902,82 +930,97 @@ 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 (Entry entry : failedARPReqList.entrySet()) { + for (Entry entry : failedARPReqList.entrySet()) { ARPPending arphost; arphost = entry.getValue(); - if (hostFinder == null) { - logger.warn("ARPHandler Services are not available on subnet addition"); + if (hostFinders.isEmpty()) { + logger.debug("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: {}", decodeIPFromId(arphost.getHostId())); + for (IHostFinder hf : hostFinders) { + hf.find(decodeIPFromId(arphost.getHostId())); + } } } } + /* + * This thread runs every 4 seconds + */ + class OutStandingARPHandler extends TimerTask { @Override public void run() { + if (stopping) { + return; + } ARPPending arphost; - - /* This routine runs every 4 seconds */ - 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 - */ - if (hostFinder == null) { - logger.warn("ARPHandler Services are not available for Outstanding ARPs"); + try { + for (Entry entry : ARPPendingList.entrySet()) { + arphost = entry.getValue(); + + if (hostsDB.containsKey(arphost.getHostId())) { + // this host is already learned, shouldn't be in + // ARPPendingList + // Remove it and continue + logger.warn("Learned Host {} found in ARPPendingList", decodeIPFromId(arphost.getHostId())); + ARPPendingList.remove(entry.getKey()); continue; } - hostFinder.find(arphost.getHostIP()); - arphost.sent_count++; - 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 - */ - ARPPendingList.remove(entry.getKey()); - logger.debug("ARP reply not received after multiple attempts, removing from Pending List IP: {}", - arphost.getHostIP().getHostAddress()); - /* - * Add this host to a different list which will be processed - * on link up events - */ - logger.debug("Adding the host to FailedARPReqList IP: {}", arphost.getHostIP().getHostAddress()); - failedARPReqList.put(entry.getKey(), arphost); + if (arphost.getSent_count() < hostRetryCount) { + /* + * No reply has been received of first ARP Req, send the + * next one. Before sending the ARP, check if ARPHandler + * is available or not + */ + if (hostFinders.isEmpty()) { + logger.warn("ARPHandler Services are not available for Outstanding ARPs"); + continue; + } + for (IHostFinder hf : hostFinders) { + hf.find(decodeIPFromId(arphost.getHostId())); + } + arphost.sent_count++; + logger.debug("ARP Sent from ARPPending List, IP: {}", decodeIPFromId(arphost.getHostId())); + } else if (arphost.getSent_count() >= hostRetryCount) { + /* + * ARP requests have been sent without receiving a + * reply, remove this from the pending list + */ + ARPPendingList.remove(entry.getKey()); + logger.debug( + "ARP reply not received after multiple attempts, removing from Pending List IP: {}", + decodeIPFromId(arphost.getHostId())); + /* + * Add this host to a different list which will be + * processed on link up events + */ + logger.debug("Adding the host to FailedARPReqList IP: {}", decodeIPFromId(arphost.getHostId())); + failedARPReqList.put(entry.getKey(), arphost); - } else { - logger.error("Inavlid arp_sent count for entry: {}", entry); + } else { + logger.error("Inavlid arp_sent count for entry: {}", entry); + } } + } catch (IllegalStateException e) { + logger.debug("IllegalStateException Received by OutStandingARPHandler from: {}", e.getMessage()); } } } private class ARPRefreshHandler extends TimerTask { @Override - @SuppressWarnings("deprecation") public void run() { if ((clusterContainerService != null) && !clusterContainerService.amICoordinator()) { return; } - if ((switchManager != null) && !switchManager.isHostRefreshEnabled()) { + if (stopping) { + return; + } + if (!hostRefresh) { /* - * The host probe procedure was disabled by CLI + * The host probe procedure is turned off */ return; } @@ -986,47 +1029,54 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw logger.error("ARPRefreshHandler(): hostsDB is not allocated yet:"); return; } - for (Entry entry : hostsDB.entrySet()) { - HostNodeConnector host = entry.getValue(); - if (host.isStaticHost()) { - /* this host was learned via API3, don't age it out */ - continue; - } - - short arp_cntdown = host.getArpSendCountDown(); - arp_cntdown--; - if (arp_cntdown > switchManager.getHostRetryCount()) { - host.setArpSendCountDown(arp_cntdown); - } else if (arp_cntdown <= 0) { - /* - * No ARP Reply received in last 2 minutes, remove this host - * and inform applications - */ - removeKnownHost(entry.getKey()); - notifyHostLearnedOrRemoved(host, false); - } else if (arp_cntdown <= switchManager.getHostRetryCount()) { - /* - * Use the services of arphandler to check if host is still - * there - */ - if (logger.isTraceEnabled()) { - logger.trace( - "ARP Probing ({}) for {}({})", - new Object[] { arp_cntdown, host.getNetworkAddress().getHostAddress(), - HexEncode.bytesToHexString(host.getDataLayerAddressBytes()) }); + try { + for (Entry entry : hostsDB.entrySet()) { + HostNodeConnector host = entry.getValue(); + if (host.isStaticHost()) { + /* this host was learned via API3, don't age it out */ + continue; } - host.setArpSendCountDown(arp_cntdown); - if (hostFinder == null) { + + short arp_cntdown = host.getArpSendCountDown(); + arp_cntdown--; + if (arp_cntdown > hostRetryCount) { + host.setArpSendCountDown(arp_cntdown); + } else if (arp_cntdown <= 0) { /* - * If hostfinder is not available, then can't send the - * probe. However, continue the age out the hosts since - * we don't know if the host is indeed out there or not. + * No ARP Reply received in last 2 minutes, remove this + * host and inform applications */ - logger.warn("ARPHandler is not avaialable, can't send the probe"); - continue; + removeKnownHost(entry.getKey()); + notifyHostLearnedOrRemoved(host, false); + } else if (arp_cntdown <= hostRetryCount) { + /* + * Use the services of arphandler to check if host is + * still there + */ + if (logger.isTraceEnabled()) { + logger.trace( + "ARP Probing ({}) for {}({})", + new Object[] { arp_cntdown, host.getNetworkAddress().getHostAddress(), + HexEncode.bytesToHexString(host.getDataLayerAddressBytes()) }); + } + host.setArpSendCountDown(arp_cntdown); + if (hostFinders.isEmpty()) { + /* + * If hostfinder is not available, then can't send + * the probe. However, continue the age out the + * hosts since we don't know if the host is indeed + * out there or not. + */ + logger.trace("ARPHandler is not avaialable, can't send the probe"); + continue; + } + for (IHostFinder hf : hostFinders) { + hf.probe(host); + } } - hostFinder.probe(host); } + } catch (IllegalStateException e) { + logger.debug("IllegalStateException Received by ARPRefreshHandler from: {}", e.getMessage()); } } } @@ -1050,7 +1100,7 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * indicating the result of this action. */ - public Status addStaticHostReq(InetAddress networkAddr, byte[] dataLayerAddress, NodeConnector nc, short vlan) { + protected Status addStaticHostReq(InetAddress networkAddr, byte[] dataLayerAddress, NodeConnector nc, short vlan) { if (dataLayerAddress.length != NetUtils.MACAddrLengthInBytes) { return new Status(StatusCode.BADREQUEST, "Invalid MAC address"); } @@ -1061,18 +1111,19 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw HostNodeConnector host = null; try { host = new HostNodeConnector(dataLayerAddress, networkAddr, nc, vlan); + IHostId id = HostIdFactory.create(networkAddr, new EthernetAddress(dataLayerAddress)); if (hostExists(host)) { // This host is already learned either via ARP or through a // northbound request HostNodeConnector transHost = hostsDB.get(networkAddr); transHost.setStaticHost(true); - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } - if (hostsDB.get(networkAddr) != null) { + if (hostsDB.get(id) != null) { // There is already a host with this IP address (but behind // a different (switch, port, vlan) tuple. Return an error - return new Status(StatusCode.CONFLICT, "Existing IP, Use PUT to update"); + return new Status(StatusCode.CONFLICT, "Host with this IP already exists."); } host.setStaticHost(true); /* @@ -1089,14 +1140,14 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw */ if (switchManager.isNodeConnectorEnabled(nc)) { learnNewHost(host); - processPendingARPReqs(networkAddr); + processPendingARPReqs(id); notifyHostLearnedOrRemoved(host, true); } else { inactiveStaticHosts.put(nc, host); logger.debug("Switch or switchport is not up, adding host {} to inactive list", networkAddr.getHostName()); } - return new Status(StatusCode.SUCCESS, null); + return new Status(StatusCode.SUCCESS); } catch (ConstructionException e) { logger.error("", e); return new Status(StatusCode.INTERNALERROR, "Host could not be created"); @@ -1140,8 +1191,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw return new Status(StatusCode.BADREQUEST, "Host already exists"); } + IHostId id = HostIdFactory.create(networkAddr, new EthernetAddress(dataLayerAddress)); + if ((tobeUpdatedHost = hostsDB.get(networkAddr)) != null) { - if (hostsDB.replace(networkAddr, tobeUpdatedHost, host)) { + if (hostsDB.replace(id, tobeUpdatedHost, host)) { logger.debug("Host replaced from hostsDB. Old host: {} New Host: {}", tobeUpdatedHost, host); notifyHostLearnedOrRemoved(tobeUpdatedHost, false); notifyHostLearnedOrRemoved(host, true); @@ -1187,9 +1240,10 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw * otherwise */ - public Status removeStaticHostReq(InetAddress networkAddress) { + public Status removeStaticHostReq(InetAddress networkAddress, DataLinkAddress mac) { // Check if host is in active hosts database - HostNodeConnector host = getHostFromOnActiveDB(networkAddress); + IHostId id = HostIdFactory.create(networkAddress, mac); + HostNodeConnector host = getHostFromOnActiveDB(id); if (host != null) { // Validation check if (!host.isStaticHost()) { @@ -1197,19 +1251,19 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } // Remove and notify notifyHostLearnedOrRemoved(host, false); - removeKnownHost(networkAddress); + removeKnownHost(id); return new Status(StatusCode.SUCCESS, null); } // Check if host is in inactive hosts database - Entry entry = getHostFromInactiveDB(networkAddress); + Entry entry = getHostFromInactiveDB(id); if (entry != null) { host = entry.getValue(); // Validation check if (!host.isStaticHost()) { return new Status(StatusCode.FORBIDDEN, "Host " + networkAddress.getHostName() + " is not static"); } - this.removeHostFromInactiveDB(networkAddress); + this.removeHostFromInactiveDB(id); return new Status(StatusCode.SUCCESS, null); } @@ -1224,13 +1278,14 @@ 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: logger.debug("Received removed node {}", node); - for (Entry entry : hostsDB.entrySet()) { + for (Entry entry : hostsDB.entrySet()) { HostNodeConnector host = entry.getValue(); if (host.getnodeconnectorNode().equals(node)) { logger.debug("Node: {} is down, remove from Hosts_DB", node); @@ -1246,8 +1301,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) { @@ -1277,38 +1333,88 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw public Status addStaticHost(String networkAddress, String dataLayerAddress, NodeConnector nc, String vlan) { try { InetAddress ip = InetAddress.getByName(networkAddress); - if (nc == null) { - return new Status(StatusCode.BADREQUEST, "Invalid NodeId"); + short vl = 0; + if (vlan != null && !vlan.isEmpty()) { + vl = Short.decode(vlan); + if (vl < 1 || vl > 4095) { + return new Status(StatusCode.BADREQUEST, "Host vlan out of range [1 - 4095]"); + } } - return addStaticHostReq(ip, HexEncode.bytesFromHexString(dataLayerAddress), nc, Short.valueOf(vlan)); + + return addStaticHostReq(ip, HexEncode.bytesFromHexString(dataLayerAddress), nc, vl); + } catch (UnknownHostException e) { - logger.error("", e); - return new Status(StatusCode.BADREQUEST, "Invalid Address"); + logger.debug("Invalid host IP specified when adding static host", e); + return new Status(StatusCode.BADREQUEST, "Invalid Host IP Address"); + } catch (NumberFormatException nfe) { + logger.debug("Invalid host vlan or MAC specified when adding static host", nfe); + return new Status(StatusCode.BADREQUEST, "Invalid Host vLan/MAC"); } } @Override public Status removeStaticHost(String networkAddress) { - InetAddress address; try { - address = InetAddress.getByName(networkAddress); - return removeStaticHostReq(address); + if ((keyScheme != null) && (!keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) { + return new Status(StatusCode.NOTALLOWED, "Host DB Key scheme used is not IP only scheme."); + } + InetAddress address = InetAddress.getByName(networkAddress); + return removeStaticHostReq(address, null); } catch (UnknownHostException e) { - logger.error("", e); - return new Status(StatusCode.BADREQUEST, "Invalid Address"); + logger.debug("Invalid IP Address when trying to remove host", e); + return new Status(StatusCode.BADREQUEST, "Invalid IP Address when trying to remove host"); + } + } + + @Override + public Status removeStaticHostUsingIPAndMac(String networkAddress, String macAddress) { + try { + if ((keyScheme != null) && (keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) { + return new Status(StatusCode.NOTALLOWED, "Host DB Key scheme used is not IP only scheme."); + } + InetAddress address = InetAddress.getByName(networkAddress); + DataLinkAddress mac = new EthernetAddress(HexEncode.bytesFromHexString(macAddress)); + return removeStaticHostReq(address, mac); + } catch (UnknownHostException e) { + logger.debug("Invalid IP Address when trying to remove host", e); + return new Status(StatusCode.BADREQUEST, "Invalid IP Address when trying to remove host"); + } catch (ConstructionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return new Status(StatusCode.BADREQUEST, "Invalid Input parameters have been passed."); + } + } + + private InetAddress decodeIPFromId(IHostId id) { + if ((keyScheme != null) && (keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) { + IPHostId ipId = (IPHostId) id; + return (ipId.getIpAddress()); + } else if ((keyScheme != null) && (keyScheme.equals(HostIdFactory.IP_MAC_KEY_SCHEME))) { + IPMacHostId ipMacId = (IPMacHostId) id; + return (ipMacId.getIpAddress()); + } + return null; + } + + private DataLinkAddress decodeMacFromId(IHostId id) { + if ((keyScheme != null) && (!keyScheme.equals(HostIdFactory.DEFAULT_IP_KEY_SCHEME))) { + IPMacHostId ipMacId = (IPMacHostId) id; + return (ipMacId.getMacAddr()); } + + return null; } private void handleNodeConnectorStatusUp(NodeConnector nodeConnector) { ARPPending arphost; HostNodeConnector host = null; - logger.debug("handleNodeConnectorStatusUp {}", nodeConnector); + logger.trace("handleNodeConnectorStatusUp {}", nodeConnector); - for (Entry entry : failedARPReqList.entrySet()) { + for (Entry entry : failedARPReqList.entrySet()) { arphost = entry.getValue(); - logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress()); - if (hostFinder == null) { + logger.trace("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostId()); + if (hostFinders.isEmpty()) { logger.warn("ARPHandler is not available at interface up"); logger.warn("Since this event is missed, host(s) connected to interface {} may not be discovered", nodeConnector); @@ -1319,29 +1425,32 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw // Use hostFinder's "probe" method try { byte[] dataLayerAddress = NetUtils.getBroadcastMACAddr(); - host = new HostNodeConnector(dataLayerAddress, arphost.getHostIP(), nodeConnector, (short) 0); - hostFinder.probe(host); + host = new HostNodeConnector(dataLayerAddress, decodeIPFromId(arphost.getHostId()), nodeConnector, + (short) 0); + for (IHostFinder hf : hostFinders) { + hf.probe(host); + } } catch (ConstructionException e) { logger.debug("HostNodeConnector couldn't be created for Host: {}, NodeConnector: {}", - arphost.getHostIP(), nodeConnector); + arphost.getHostId(), nodeConnector); logger.error("", e); } - logger.debug("Done. handleNodeConnectorStatusUp {}", nodeConnector); } host = inactiveStaticHosts.get(nodeConnector); if (host != null) { inactiveStaticHosts.remove(nodeConnector); learnNewHost(host); - processPendingARPReqs(host.getNetworkAddress()); + IHostId id = HostIdFactory.create(host.getNetworkAddress(), host.getDataLayerAddress()); + processPendingARPReqs(id); notifyHostLearnedOrRemoved(host, true); } } private void handleNodeConnectorStatusDown(NodeConnector nodeConnector) { - logger.debug("handleNodeConnectorStatusDown {}", nodeConnector); + logger.trace("handleNodeConnectorStatusDown {}", nodeConnector); - for (Entry entry : hostsDB.entrySet()) { + for (Entry entry : hostsDB.entrySet()) { HostNodeConnector host = entry.getValue(); if (host.getnodeConnector().equals(nodeConnector)) { logger.debug(" NodeConnector: {} is down, remove from Hosts_DB", nodeConnector); @@ -1376,8 +1485,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw } public String getContainerName() { - if (containerName == null) + if (containerName == null) { return GlobalConstants.DEFAULT.toString(); + } return containerName; } @@ -1396,6 +1506,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw this.containerName = ""; } startUp(); + + logger.debug("key Scheme in hosttracker is {}", keyScheme); } /** @@ -1422,42 +1534,40 @@ 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(IHostId 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(IHostId key, HostNodeConnector new_value, String cacheName, boolean originLocal) { } @Override - public void entryDeleted(InetAddress key, String cacheName, - boolean originLocal) { + public void entryDeleted(IHostId key, String cacheName, boolean originLocal) { } private void registerWithOSGIConsole() { @@ -1467,23 +1577,66 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw @Override public String getHelp() { - // TODO Auto-generated method stub return null; } public void _dumpPendingARPReqList(CommandInterpreter ci) { ARPPending arphost; - for (Entry entry : ARPPendingList.entrySet()) { + for (Entry entry : ARPPendingList.entrySet()) { arphost = entry.getValue(); - ci.println(arphost.getHostIP().toString()); + ci.println(arphost.getHostId().toString()); } } public void _dumpFailedARPReqList(CommandInterpreter ci) { ARPPending arphost; - for (Entry entry : failedARPReqList.entrySet()) { + for (Entry entry : failedARPReqList.entrySet()) { arphost = entry.getValue(); - ci.println(arphost.getHostIP().toString()); + ci.println(arphost.getHostId().toString()); + } + } + + @Override + public HostNodeConnector hostFind(InetAddress addr) { + IHostId id = HostIdFactory.create(addr, null); + return (hostFind(id)); + } + + @Override + public HostNodeConnector hostQuery(InetAddress addr) { + IHostId id = HostIdFactory.create(addr, null); + return (hostQuery(id)); + } + + @Override + public Future discoverHost(InetAddress addr) { + IHostId id = HostIdFactory.create(addr, null); + return discoverHost(id); + } + + @Override + public List> getHostNetworkHierarchy(InetAddress addr) { + IHostId id = HostIdFactory.create(addr, null); + return getHostNetworkHierarchy(id); + } + + @Override + public List dumpPendingArpReqList() { + ARPPending arphost; + List arpReq = new ArrayList(); + for (Entry entry : ARPPendingList.entrySet()) { + arpReq.add(entry.getValue().getHostId().toString()); + } + return arpReq; + } + + @Override + public List dumpFailedArpReqList() { + ARPPending arphost; + List arpReq = new ArrayList(); + for (Entry entry : failedARPReqList.entrySet()) { + arpReq.add(entry.getValue().getHostId().toString()); } + return arpReq; } }