import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
+import org.opendaylight.controller.containermanager.IContainerManager;
import org.opendaylight.controller.forwardingrulesmanager.
IForwardingRulesManager;
import org.opendaylight.controller.hosttracker.IfHostListener;
list.add(IFlowProgrammerListener.class.getName());
if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
list.add(IContainerListener.class.getName());
+
+ c.add(createServiceDependency().
+ setService(IContainerManager.class).
+ setCallbacks("setContainerManager",
+ "unsetContainerManager").
+ setRequired(true));
}
// Export IVTNFlowDebugger only if "vtn.debug" system property
} catch (Exception e) {
LOG.error(containerName + ": Failed to clean up resource", e);
}
- }
+ if (vtnManagers.size() == 1) {
+ // The controller quits the container mode.
+ // Some FLOW_REMOVED notifications might be ignored when the
+ // controller entered the container mode.
+ // So we need to clean up them.
+ VTNManagerImpl mgr =
+ vtnManagers.get(GlobalConstants.DEFAULT.toString());
+ mgr.cleanUpRemovedFlows();
+ }
+ }
/**
* {@inheritDoc}
--- /dev/null
+/*
+ * Copyright (c) 2014 NEC Corporation
+ * All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vtn.manager.internal;
+
+import java.util.HashSet;
+import java.util.List;
+
+import org.opendaylight.vtn.manager.internal.cluster.VTNFlow;
+
+import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
+import org.opendaylight.controller.forwardingrulesmanager.
+ IForwardingRulesManager;
+
+/**
+ * {@link VTNFlowMatch} implementation which accepts VTN flows which are
+ * already removed.
+ */
+public class RemovedFlowMatch implements VTNFlowMatch {
+ /**
+ * Forwarding rules manager service.
+ */
+ private final IForwardingRulesManager fwRulesManager;
+
+ /**
+ * Construct a new instance.
+ *
+ * @param frm Forwarding rules manager service.
+ */
+ public RemovedFlowMatch(IForwardingRulesManager frm) {
+ fwRulesManager = frm;
+ }
+
+ /**
+ * Test if the specified VTN flow should be accepted or not.
+ *
+ * @param vflow A {@link VTNFlow} instance to be tested.
+ * @return {@code true} if the specified flow is already removed.
+ * Otherwise {@code false}.
+ */
+ @Override
+ public boolean accept(VTNFlow vflow) {
+ HashSet<String> installed = new HashSet<String>();
+ String group = vflow.getGroupId().toString();
+ for (FlowEntry fent: fwRulesManager.getFlowEntriesForGroup(group)) {
+ installed.add(fent.getFlowName());
+ }
+
+ List<FlowEntry> entries = vflow.getFlowEntries();
+ if (entries.size() != installed.size()) {
+ return true;
+ }
+
+ for (FlowEntry fent: entries) {
+ if (!installed.contains(fent.getFlowName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getDescription() {
+ return "removed";
+ }
+}
import org.opendaylight.controller.sal.utils.EtherTypes;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.NetUtils;
-import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
*/
private IConnectionManager connectionManager;
+ /**
+ * Container manager service instance.
+ *
+ * <p>
+ * Note that {@code null} is set unless this instance is associated with
+ * the default container.
+ * </p>
+ */
+ private IContainerManager containerManager;
+
/**
* Host listeners.
*/
String root = GlobalConstants.STARTUPHOME.toString();
vtnConfig = new VTNConfig(root, cname);
- if (cname.equals(GlobalConstants.DEFAULT.toString())) {
- IContainerManager ctMgr = (IContainerManager)ServiceHelper.
- getGlobalInstance(IContainerManager.class, this);
- inContainerMode =
- (ctMgr != null && ctMgr.hasNonDefaultContainer());
+ if (containerManager != null) {
+ assert containerName.equals(GlobalConstants.DEFAULT.toString());
+ inContainerMode = containerManager.inContainerMode();
} else {
inContainerMode = false;
}
return connectionManager;
}
+ /**
+ * Invoked when a container manager service is registered.
+ *
+ * @param service Container manager service.
+ */
+ void setContainerManager(IContainerManager service) {
+ LOG.trace("{}: Set container manager service: {}", containerName,
+ service);
+ containerManager = service;
+ }
+
+ /**
+ * Invoked when a container manager service is unregistered.
+ *
+ * @param service Container manager service.
+ */
+ void unsetContainerManager(IContainerManager service) {
+ if (containerManager == service) {
+ LOG.trace("{}: Unset container manager service: {}",
+ containerName, service);
+ containerManager = null;
+ }
+ }
+
+ /**
+ * Return container manager service instance.
+ *
+ * @return Container manager service.
+ * Note that {@code null} is always returned unless this instance
+ * is associated with the default container.
+ */
+ public IContainerManager getContainerManager() {
+ return containerManager;
+ }
+
/**
* Invoked when a host listener is registered.
*
}
}
+ /**
+ * Collect inactive flows and remove them in background.
+ */
+ public void cleanUpRemovedFlows() {
+ if (clusterService.amICoordinator()) {
+ RemovedFlowMatch fmatch = new RemovedFlowMatch(fwRuleManager);
+ for (VTNFlowDatabase fdb: vtnFlowMap.values()) {
+ fdb.removeFlows(this, fmatch);
+ }
+ }
+ }
+
/**
* Determine whether the given node connector is associated with the
* physical switch port at the edge of the SDN network.
}
} else if (arpHandler == null) {
// Inactivate VTN, and start ARP handler emulator.
- for (VTNFlowDatabase fdb: vtnFlowMap.values()) {
- VTNThreadData.removeFlows(this, fdb);
- }
arpHandler = new ArpHandler(this);
if (sync) {
notifyListeners(false);
public List<DataFlow> getDataFlows(VTenantPath path, DataFlow.Mode mode,
DataFlowFilter filter)
throws VTNException {
+ if (inContainerMode) {
+ // No flow entry is active in container mode.
+ // It's harmless to access inContainerMode flag without holding
+ // rmLock.
+ return new ArrayList<DataFlow>(0);
+ }
+
// We should not acquire lock here because succeeding method call may
// make requests to get flow statistics. Synchronization will be done
// by VTNFlowDatabase appropriately.
public DataFlow getDataFlow(VTenantPath path, long flowId,
DataFlow.Mode mode)
throws VTNException {
+ if (inContainerMode) {
+ // No flow entry is active in container mode.
+ // It's harmless to access inContainerMode flag without holding
+ // rmLock.
+ return null;
+ }
+
// We should not acquire lock here because succeeding method call may
// make requests to get flow statistics. Synchronization will be done
// by VTNFlowDatabase appropriately.
*/
@Override
public int getDataFlowCount(VTenantPath path) throws VTNException {
+ if (inContainerMode) {
+ // No flow entry is active in container mode.
+ // It's harmless to access inContainerMode flag without holding
+ // rmLock.
+ return 0;
+ }
+
VTNFlowDatabase fdb = getTenantFlowDB(path);
return fdb.getFlowCount();
}
*/
@Override
public void flowRemoved(Node node, Flow flow) {
+ if (containerManager != null && containerManager.inContainerMode()) {
+ // The given flow was removed by forwarding rule manager, and it
+ // will be restored when the controller exits the container mode.
+ // Note that we can not use inContainerMode variable here because
+ // containerModeUpdated() handler for FRM may be called before
+ // the VTN Manager. Although this code may miss FLOW_REMOVED
+ // notifications actually sent by OF switch, they will be fixed
+ // when the controller quits the container mode.
+ assert containerName.equals(GlobalConstants.DEFAULT.toString());
+ LOG.trace("{}: Ignore FLOW_REMOVED during container mode: " +
+ "node={}, flow={}", containerName, node, flow);
+ return;
+ }
+
LOG.trace("{}: flowRemoved() called: node={}, flow={}",
containerName, node, flow);
vtnMgr.setHostTracker(stubObj);
vtnMgr.setForwardingRuleManager(stubObj);
vtnMgr.setConnectionManager(cm);
+ vtnMgr.setContainerManager(stubObj);
startVTNManager(c);
}
import org.opendaylight.controller.clustering.services.IClusterServices.cacheMode;
import org.opendaylight.controller.connectionmanager.ConnectionMgmtScheme;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
+import org.opendaylight.controller.containermanager.ContainerConfig;
+import org.opendaylight.controller.containermanager.ContainerFlowConfig;
+import org.opendaylight.controller.containermanager.IContainerManager;
import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
import org.opendaylight.controller.sal.packet.Packet;
import org.opendaylight.controller.sal.packet.RawPacket;
import org.opendaylight.controller.sal.routing.IRouting;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.NodeCreator;
implements IClusterGlobalServices, IClusterContainerServices,
ISwitchManager, ITopologyManager, IDataPacketService, IRouting,
IForwardingRulesManager, IfIptoHost, IConnectionManager,
- IfHostListener {
+ IfHostListener, IContainerManager {
/**
* The name of the cluster cache which keeps revision identifier of
* configuration per mapping type.
return null;
}
+ // IContainerManager
+
+ @Override
+ public Status addContainer(ContainerConfig configObject) {
+ return null;
+ }
+
+ @Override
+ public Status removeContainer(ContainerConfig configObject) {
+ return null;
+ }
+
+ @Override
+ public Status removeContainer(String containerName) {
+ return null;
+ }
+
+ @Override
+ public Status addContainerEntry(String containerName,
+ List<String> portList) {
+ return null;
+ }
+
+ @Override
+ public Status removeContainerEntry(String containerName,
+ List<String> portList) {
+ return null;
+ }
+
+ @Override
+ public Status addContainerFlows(String containerName,
+ List<ContainerFlowConfig> configObject) {
+ return null;
+ }
+
+ @Override
+ public Status removeContainerFlows(String containerName,
+ List<ContainerFlowConfig> configObject) {
+ return null;
+ }
+
+ @Override
+ public Status removeContainerFlows(String containerName, Set<String> name) {
+ return null;
+ }
+
+ @Override
+ public List<ContainerConfig> getContainerConfigList() {
+ return null;
+ }
+
+ @Override
+ public ContainerConfig getContainerConfig(String containerName) {
+ return null;
+ }
+
+ @Override
+ public List<String> getContainerNameList() {
+ return null;
+ }
+
+ @Override
+ public boolean doesContainerExist(String ContainerId) {
+ return GlobalConstants.DEFAULT.toString().equals(ContainerId);
+ }
+
+ @Override
+ public Map<String, List<ContainerFlowConfig>> getContainerFlows() {
+ return null;
+ }
+
+ @Override
+ public List<ContainerFlowConfig> getContainerFlows(String containerName) {
+ return null;
+ }
+
+ @Override
+ public List<String> getContainerFlowNameList(String containerName) {
+ return null;
+ }
+
+ @Override
+ public boolean hasNonDefaultContainer() {
+ return false;
+ }
+
+ @Override
+ public List<String> getContainerNames() {
+ return null;
+ }
+
+ @Override
+ public boolean inContainerMode() {
+ return false;
+ }
+
// additional method for control stub
public void addEdge(Edge edge) {
Map<Node, List<Edge>> map = nodeEdges.get(edge.getTailNodeConnector().getNode());
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Dictionary;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import org.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.containermanager.IContainerManager;
import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
import org.opendaylight.controller.hosttracker.IfHostListener;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
vtnMgr.setHostTracker(stubObj);
vtnMgr.setForwardingRuleManager(stubObj);
vtnMgr.setConnectionManager(stubObj);
+ vtnMgr.setContainerManager(stubObj);
startVTNManager(c);
if (stubObj.isHostTrackerEnabled()) {
vtnMgr.addHostListener(stubObj);
* startup VTNManager.
*/
protected void startVTNManager(ComponentImpl c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ if (props != null) {
+ String name = (String)props.get("containerName");
+ IContainerManager ctmgr = vtnMgr.getContainerManager();
+ if (GlobalConstants.DEFAULT.toString().equals(name)) {
+ if (ctmgr == null) {
+ vtnMgr.setContainerManager(stubObj);
+ }
+ } else if (ctmgr != null) {
+ vtnMgr.unsetContainerManager(ctmgr);
+ }
+ }
vtnMgr.init(c);
vtnMgr.clearDisabledNode();
}
vtnMgr.setHostTracker(stub);
vtnMgr.setForwardingRuleManager(stub);
vtnMgr.setConnectionManager(stub);
+ vtnMgr.setContainerManager(stub);
startVTNManager(c);
if (stub.isHostTrackerEnabled()) {
vtnMgr.addHostListener(stub);
vtnMgr.setHostTracker(stubObj);
vtnMgr.setForwardingRuleManager(stubObj);
vtnMgr.setConnectionManager(stubObj);
+ vtnMgr.setContainerManager(stubObj);
startVTNManager(c);
}
vtnMgr.setHostTracker(stubObj);
vtnMgr.setForwardingRuleManager(stubObj);
vtnMgr.setConnectionManager(stubObj);
+ vtnMgr.setContainerManager(stubObj);
startVTNManager(c);
}
vtnMgr.setHostTracker(stubObj);
vtnMgr.setForwardingRuleManager(stubObj);
vtnMgr.setConnectionManager(stubObj);
+ vtnMgr.setContainerManager(stubObj);
vtnMgr.init(c);
vtnMgr.clearDisabledNode();
}
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
+import org.opendaylight.controller.containermanager.IContainerManager;
import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
import org.opendaylight.controller.hosttracker.IfHostListener;
assertSame(org, mgr.getConnectionManager());
}
+ /**
+ * Test method for
+ * {@link VTNManagerImpl#setContainerManager(IContainerManager)},
+ * {@link VTNManagerImpl#unsetContainerManager(IContainerManager)},
+ * {@link VTNManagerImpl#getContainerManager()}
+ * .
+ */
+ @Test
+ public void testSetUnsetContainerManager() {
+ VTNManagerImpl mgr = vtnMgr;
+ IContainerManager org = mgr.getContainerManager();
+ TestStub stub = new TestStub();
+ TestStub stub2 = new TestStub();
+
+ mgr.setContainerManager(stub);
+ assertSame(stub, mgr.getContainerManager());
+
+ mgr.unsetContainerManager(stub2);
+ assertSame(stub, mgr.getContainerManager());
+
+ mgr.unsetContainerManager(stub);
+ assertNull(mgr.getContainerManager());
+
+ mgr.setContainerManager(org);
+ assertSame(org, mgr.getContainerManager());
+ }
+
/**
* Test method for
* {@link VTNManagerImpl#setResourceManager(IVTNResourceManager)},