X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fforwarding%2Fstaticrouting%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fforwarding%2Fstaticrouting%2Finternal%2FStaticRoutingImplementation.java;h=2ce2465d976e28a82a7a3bc8e66ddc9df144300c;hp=fd043fd0ac321d4cc52ce294676b5558ee72fac4;hb=f062dc05cc7caaf0c1811856370f1c9e2f1e5c34;hpb=29f7cfb54b580928c7feac63abce028a7014b0d5 diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java index fd043fd0ac..2ce2465d97 100644 --- a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java +++ b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -16,7 +15,6 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.nio.ByteBuffer; import java.util.Collections; -import java.util.Date; import java.util.Dictionary; import java.util.EnumSet; import java.util.HashSet; @@ -24,8 +22,11 @@ import java.util.Map; import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -33,7 +34,6 @@ import java.util.regex.Pattern; import org.apache.felix.dm.Component; import org.opendaylight.controller.clustering.services.CacheConfigException; 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.configuration.IConfigurationContainerAware; @@ -41,40 +41,36 @@ import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRou import org.opendaylight.controller.forwarding.staticrouting.IStaticRoutingAware; import org.opendaylight.controller.forwarding.staticrouting.StaticRoute; import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig; +import org.opendaylight.controller.hosttracker.HostIdFactory; +import org.opendaylight.controller.hosttracker.IHostId; import org.opendaylight.controller.hosttracker.IfIptoHost; import org.opendaylight.controller.hosttracker.IfNewHostNotify; import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector; -import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.IObjectReader; import org.opendaylight.controller.sal.utils.ObjectReader; import org.opendaylight.controller.sal.utils.ObjectWriter; import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Static Routing feature provides the bridge between SDN and Non-SDN networks. - * - * - * */ -public class StaticRoutingImplementation implements IfNewHostNotify, - IForwardingStaticRouting, IObjectReader, IConfigurationContainerAware, - ICacheUpdateAware { - private static Logger log = LoggerFactory - .getLogger(StaticRoutingImplementation.class); +public class StaticRoutingImplementation implements IfNewHostNotify, IForwardingStaticRouting, IObjectReader, + IConfigurationContainerAware { + private static Logger log = LoggerFactory.getLogger(StaticRoutingImplementation.class); private static String ROOT = GlobalConstants.STARTUPHOME.toString(); - private static final String SAVE = "Save"; ConcurrentMap staticRoutes; ConcurrentMap staticRouteConfigs; private IfIptoHost hostTracker; private Timer gatewayProbeTimer; private String staticRoutesFileName = null; - private Map configSaveEvent; private IClusterContainerServices clusterContainerService = null; private Set staticRoutingAware = Collections .synchronizedSet(new HashSet()); + private ExecutorService executor; void setStaticRoutingAware(IStaticRoutingAware s) { if (this.staticRoutingAware != null) { @@ -99,18 +95,13 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } } + @Override public ConcurrentMap getStaticRouteConfigs() { return staticRouteConfigs; } - public void setStaticRouteConfigs( - ConcurrentMap staticRouteConfigs) { - this.staticRouteConfigs = staticRouteConfigs; - } - @Override - public Object readObject(ObjectInputStream ois) - throws FileNotFoundException, IOException, ClassNotFoundException { + public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException { // Perform the class deserialization locally, from inside the package // where the class is defined return ois.readObject(); @@ -119,8 +110,8 @@ public class StaticRoutingImplementation implements IfNewHostNotify, @SuppressWarnings("unchecked") private void loadConfiguration() { ObjectReader objReader = new ObjectReader(); - ConcurrentMap confList = (ConcurrentMap) objReader - .read(this, staticRoutesFileName); + ConcurrentMap confList = (ConcurrentMap) objReader.read( + this, staticRoutesFileName); if (confList == null) { return; @@ -131,10 +122,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } } - @Override - public Status saveConfig() { - // Publish the save config event to the cluster nodes - configSaveEvent.put(new Date().getTime(), SAVE); + private Status saveConfig() { return saveConfigInternal(); } @@ -142,9 +130,8 @@ public class StaticRoutingImplementation implements IfNewHostNotify, Status status; ObjectWriter objWriter = new ObjectWriter(); - status = objWriter.write( - new ConcurrentHashMap( - staticRouteConfigs), staticRoutesFileName); + status = objWriter.write(new ConcurrentHashMap(staticRouteConfigs), + staticRoutesFileName); if (status.isSuccess()) { return status; @@ -154,27 +141,19 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } @SuppressWarnings("deprecation") - private void allocateCaches() { + private void allocateCaches() { if (this.clusterContainerService == null) { - log - .info("un-initialized clusterContainerService, can't create cache"); + log.info("un-initialized clusterContainerService, can't create cache"); return; } try { - clusterContainerService.createCache( - "forwarding.staticrouting.routes", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); - clusterContainerService.createCache( - "forwarding.staticrouting.configs", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); - clusterContainerService.createCache( - "forwarding.staticrouting.configSaveEvent", EnumSet - .of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); - + clusterContainerService.createCache("forwarding.staticrouting.routes", + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); + clusterContainerService.createCache("forwarding.staticrouting.configs", + EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL)); } catch (CacheExistException cee) { - log - .error("\nCache already exists - destroy and recreate if needed"); + log.error("\nCache already exists - destroy and recreate if needed"); } catch (CacheConfigException cce) { log.error("\nCache configuration invalid - check cache mode"); } @@ -183,8 +162,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify, @SuppressWarnings({ "unchecked", "deprecation" }) private void retrieveCaches() { if (this.clusterContainerService == null) { - log - .info("un-initialized clusterContainerService, can't retrieve cache"); + log.info("un-initialized clusterContainerService, can't retrieve cache"); return; } @@ -199,41 +177,6 @@ public class StaticRoutingImplementation implements IfNewHostNotify, if (staticRouteConfigs == null) { log.error("\nFailed to get rulesDB handle"); } - configSaveEvent = (ConcurrentMap) clusterContainerService - .getCache("forwarding.staticrouting.configSaveEvent"); - if (configSaveEvent == null) { - log.error("\nFailed to get cache for configSaveEvent"); - } - } - - @SuppressWarnings("deprecation") - private void destroyCaches() { - if (this.clusterContainerService == null) { - log - .info("un-initialized clusterContainerService, can't destroy cache"); - return; - } - - clusterContainerService.destroyCache("forwarding.staticrouting.routes"); - clusterContainerService - .destroyCache("forwarding.staticrouting.configs"); - clusterContainerService - .destroyCache("forwarding.staticrouting.configSaveEvent"); - - } - - @Override - public void entryCreated(Long key, String cacheName, boolean local) { - } - - @Override - public void entryUpdated(Long key, String new_value, String cacheName, - boolean originLocal) { - saveConfigInternal(); - } - - @Override - public void entryDeleted(Long key, String cacheName, boolean originLocal) { } private void notifyStaticRouteUpdate(StaticRoute s, boolean update) { @@ -244,65 +187,92 @@ public class StaticRoutingImplementation implements IfNewHostNotify, try { ra.staticRouteUpdate(s, update); } catch (Exception e) { - e.printStackTrace(); + log.error("", e); } } } } } - private class NotifyStaticRouteThread extends Thread { + private class NotifyStaticRouteWorker implements Callable { + + private String name; private StaticRoute staticRoute; private boolean added; - public NotifyStaticRouteThread(StaticRoute s, boolean update) { + public NotifyStaticRouteWorker(String name, StaticRoute s, boolean update) { + this.name = name; this.staticRoute = s; this.added = update; } - public void run() { - if (!added - || (staticRoute.getType() == StaticRoute.NextHopType.SWITCHPORT)) { + @Override + public Object call() throws Exception { + if (!added || (staticRoute.getType() == StaticRoute.NextHopType.SWITCHPORT)) { notifyStaticRouteUpdate(staticRoute, added); } else { - HostNodeConnector host = hostTracker.hostQuery(staticRoute - .getNextHopAddress()); + InetAddress nh = staticRoute.getNextHopAddress(); + // HostTracker hosts db key scheme implementation + IHostId id = HostIdFactory.create(nh, null); + HostNodeConnector host = hostTracker.hostQuery(id); if (host == null) { - Future future = hostTracker - .discoverHost(staticRoute.getNextHopAddress()); + log.debug("Next hop {} is not present, try to discover it", nh.getHostAddress()); + Future future = hostTracker.discoverHost(id); if (future != null) { try { host = future.get(); + } catch (InterruptedException ioe) { + log.trace("Thread interrupted {}", ioe); } catch (Exception e) { - e.printStackTrace(); + log.error("", e); } } } if (host != null) { + log.debug("Next hop {} is found", nh.getHostAddress()); staticRoute.setHost(host); + // static route object has changed + // put the changed object back in the cache + // for it to sync + staticRoutes.put(name, staticRoute); notifyStaticRouteUpdate(staticRoute, added); + } else { + log.debug("Next hop {} is still not present, try again later", nh.getHostAddress()); } } + return null; } } - private void checkAndUpdateListeners(StaticRoute staticRoute, boolean added) { - new NotifyStaticRouteThread(staticRoute, added).start(); + private void checkAndUpdateListeners(String name, StaticRoute staticRoute, boolean added) { + NotifyStaticRouteWorker worker = new NotifyStaticRouteWorker(name, staticRoute, added); + try { + executor.submit(worker); + } catch (Exception e) { + log.error("got Exception ", e); + } } private void notifyHostUpdate(HostNodeConnector host, boolean added) { - if (host == null) + if (host == null) { return; - for (StaticRoute s : staticRoutes.values()) { - if (s.getType() == StaticRoute.NextHopType.SWITCHPORT) + } + for (Map.Entry s : staticRoutes.entrySet()) { + StaticRoute route = s.getValue(); + if (route.getType() == StaticRoute.NextHopType.SWITCHPORT) { continue; - if (s.getNextHopAddress().equals(host.getNetworkAddress())) { + } + if (route.getNextHopAddress().equals(host.getNetworkAddress())) { if (added) { - s.setHost(host); + route.setHost(host); } else { - s.setHost(null); + route.setHost(null); } - notifyStaticRouteUpdate(s, added); + // static route object has changed + // put the changed object back in the cache + // for it to sync + staticRoutes.put(s.getKey(), route); + notifyStaticRouteUpdate(route, added); } } } @@ -318,8 +288,9 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } public boolean isIPv4AddressValid(String cidr) { - if (cidr == null) + if (cidr == null) { return false; + } String values[] = cidr.split("/"); Pattern ipv4Pattern = Pattern @@ -355,11 +326,11 @@ public class StaticRoutingImplementation implements IfNewHostNotify, return 0; } + @Override public StaticRoute getBestMatchStaticRoute(InetAddress ipAddress) { ByteBuffer bblongestPrefix = null; try { - bblongestPrefix = ByteBuffer.wrap(InetAddress.getByName("0.0.0.0") - .getAddress()); + bblongestPrefix = ByteBuffer.wrap(InetAddress.getByName("0.0.0.0").getAddress()); } catch (Exception e) { return null; } @@ -382,43 +353,45 @@ public class StaticRoutingImplementation implements IfNewHostNotify, return longestPrefixRoute; } + @Override public Status addStaticRoute(StaticRouteConfig config) { - Status status; - - status = config.isValid(); + Status status = config.isValid(); if (!status.isSuccess()) { return status; } if (staticRouteConfigs.get(config.getName()) != null) { - return new Status(StatusCode.CONFLICT, - "A valid Static Route configuration with this name " + - "already exists. Please use a different name"); + return new Status(StatusCode.CONFLICT, "A valid Static Route configuration with this name " + + "already exists. Please use a different name"); } - for (StaticRouteConfig s : staticRouteConfigs.values()) { - if (s.equals(config)) { - return new Status(StatusCode.CONFLICT, - "This conflicts with an existing Static Route " + - "Configuration. Please check the configuration " + - "and try again"); + + // Update database + StaticRoute sRoute = new StaticRoute(config); + + for (Map.Entry entry : staticRoutes.entrySet()) { + if (entry.getValue().compareTo(sRoute) == 0) { + return new Status(StatusCode.CONFLICT, "This conflicts with an existing Static Route " + + "Configuration. Please check the configuration " + "and try again"); } } + staticRoutes.put(config.getName(), sRoute); + // Update config databse staticRouteConfigs.put(config.getName(), config); - StaticRoute sRoute = new StaticRoute(config); - staticRoutes.put(config.getName(), sRoute); - checkAndUpdateListeners(sRoute, true); - return status; + + // Notify + checkAndUpdateListeners(config.getName(), sRoute, true); + return status; } + @Override public Status removeStaticRoute(String name) { staticRouteConfigs.remove(name); StaticRoute sRoute = staticRoutes.remove(name); if (sRoute != null) { - checkAndUpdateListeners(sRoute, false); + checkAndUpdateListeners(name, sRoute, false); return new Status(StatusCode.SUCCESS, null); } - return new Status(StatusCode.NOTFOUND, - "Static Route with name " + name + " is not found"); + return new Status(StatusCode.NOTFOUND, "Static Route with name " + name + " is not found"); } void setClusterContainerService(IClusterContainerServices s) { @@ -448,47 +421,44 @@ public class StaticRoutingImplementation implements IfNewHostNotify, containerName = ""; } - staticRoutesFileName = ROOT + "staticRouting_" + containerName - + ".conf"; + staticRoutesFileName = ROOT + "staticRouting_" + containerName + ".conf"; - log.debug("forwarding.staticrouting starting on container " - + containerName); - //staticRoutes = new ConcurrentHashMap(); + log.debug("forwarding.staticrouting starting on container {}", containerName); allocateCaches(); retrieveCaches(); - - if (staticRouteConfigs.isEmpty()) + this.executor = Executors.newFixedThreadPool(1); + if (staticRouteConfigs.isEmpty()) { loadConfiguration(); + } /* - * Slow probe to identify any gateway that might have silently appeared - * after the Static Routing Configuration. + * Slow probe to identify any gateway that might have silently appeared + * after the Static Routing Configuration. */ gatewayProbeTimer = new Timer(); gatewayProbeTimer.schedule(new TimerTask() { @Override public void run() { - for (StaticRoute s : staticRoutes.values()) { - if ((s.getType() == StaticRoute.NextHopType.IPADDRESS) - && s.getHost() == null) { - checkAndUpdateListeners(s, true); + for (Map.Entry s : staticRoutes.entrySet()) { + StaticRoute route = s.getValue(); + if ((route.getType() == StaticRoute.NextHopType.IPADDRESS) && route.getHost() == null) { + checkAndUpdateListeners(s.getKey(), route, true); } } } }, 60 * 1000, 60 * 1000); + } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. * */ void destroy() { - log.debug("Destroy all the Static Routing Rules given we are " - + "shutting down"); + log.debug("Destroy all the Static Routing Rules given we are " + "shutting down"); - destroyCaches(); gatewayProbeTimer.cancel(); // Clear the listener so to be ready in next life @@ -496,25 +466,26 @@ public class StaticRoutingImplementation implements IfNewHostNotify, } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry * */ void start() { } /** - * Function called by the dependency manager before the services - * exported by the component are unregistered, this will be - * followed by a "destroy ()" calls + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls * */ void stop() { + executor.shutdown(); } @Override public Status saveConfiguration() { return this.saveConfig(); } + }