<classifier>config</classifier>
<type>xml</type>
</dependency>
-
-
+
+
<dependency>
<groupId>org.opendaylight.dlux</groupId>
<artifactId>features-dlux</artifactId>
<classifier>features</classifier>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-netconf-connector</artifactId>
+ <version>${netconf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
<!-- bundle dependencies -->
<dependency>
<repository>mvn:org.opendaylight.openflowjava/features-openflowjava/${openflowjava.version}/xml/features</repository>
<repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
<repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+ <!-- repository>mvn:org.opendaylight.controller/features-netconf-connector/${netconf.version}/xml/features</repository -->
<feature name='odl-openflowplugin-all' description="OpenDaylight :: Openflow Plugin :: All" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-southbound</feature>
<feature version="${project.version}">odl-openflowplugin-app-config-pusher</feature>
<feature version="${project.version}">odl-openflowplugin-app-lldp-speaker</feature>
</feature>
-
+
<feature name='odl-openflowplugin-nsf-services' version='${project.version}'
description="OpenDaylight :: OpenflowPlugin :: NSF :: Services">
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<bundle>mvn:org.opendaylight.controller/liblldp/${sal.api.version}</bundle>
<configfile finalname="${config.configfile.directory}/${config.statistics.manager.configfile}">mvn:org.opendaylight.openflowplugin.applications/statistics-manager-config/${project.version}/xml/config</configfile>
</feature>
-
+
<feature name='odl-openflowplugin-nsf-model' version='${project.version}'
description="OpenDaylight :: OpenflowPlugin :: NSF :: Model">
<!-- general models -->
<bundle>mvn:org.opendaylight.openflowplugin.model/model-flow-statistics/${project.version}</bundle>
<bundle>mvn:org.opendaylight.openflowplugin.model/model-flow-service/${project.version}</bundle>
</feature>
-
+
<feature name='odl-openflowplugin-flow-services-rest' description="OpenDaylight :: Openflow Plugin :: Flow Services :: REST" version='${project.version}'>
+ <!-- feature version="${netconf.version}">odl-netconf-connector-ssh</feature -->
<feature version="${project.version}">odl-openflowplugin-flow-services</feature>
<feature version="${mdsal.version}">odl-restconf</feature>
</feature>
<feature version="${mdsal.version}">odl-mdsal-apidocs</feature>
<feature version="${mdsal.version}">odl-mdsal-xsql</feature>
</feature>
-
+
<!-- CBENCH TESTING -->
<feature name='odl-openflowplugin-drop-test' description="OpenDaylight :: Openflow Plugin :: Drop Test" version='${project.version}'>
<feature version="${project.version}">odl-openflowplugin-flow-services</feature>
*/
public interface IMessageDispatchService {
+ public static final String CONNECTION_ERROR_MESSAGE = "Session for the cookie is invalid. Reason: "
+ + "the switch has been recently disconnected OR inventory provides outdated information.";
+
/**
* send barrier message to switch
*
import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationQueueWrapper;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
* @return The Map of OFPhysicalPort
*/
Map<Long, PortGrouping> getPhysicalPorts();
-
+
/**
* Returns a map containing all bandwidths for all OFPorts of this switch.
* @return The Map of bandwidths for all OFPorts
* @return The Set of port ID
*/
Set<Long> getPorts();
-
+
/**
* Returns OFPhysicalPort of the specified portNumber of this switch.
* @param portNumber The port ID
* @return provider composite registration
*/
CompositeObjectRegistration<ModelDrivenSwitch> getProviderRegistration();
-
+
/**
* @return seed value for random operations
*/
int getSeed();
-
+
/**
* @return (wrapped) notification enqueue service - {@link NotificationQueueWrapper}
*/
NotificationEnqueuer getNotificationEnqueuer();
+
+ /**
+ * @param roleOnDevice
+ */
+ void setRoleOnDevice(ControllerRole roleOnDevice);
+
+ /**
+ * @return actual role
+ */
+ ControllerRole getRoleOnDevice();
}
*/
MessageSpy<DataContainer> getMessageSpy();
+ /**
+ * @return collection of current sessions
+ */
+ Collection<SessionContext> getAllSessions();
}
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.sal.NotificationComposer;
import org.opendaylight.openflowplugin.api.statistics.MessageSpy;
-import org.opendaylight.openflowplugin.openflow.md.core.MessageFactory;
-import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
-import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.openflow.md.util.RpcInputOutputTuple;
+import org.opendaylight.openflowplugin.openflow.md.util.TaskUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionAware;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
/**
Collection<RpcError> errors = null;
if (Objects.firstNonNull(isBarrier, Boolean.FALSE)) {
RpcInputOutputTuple<BarrierInput, ListenableFuture<RpcResult<BarrierOutput>>> sendBarrierRpc =
- sendBarrier(taskContext.getSession(), cookie, taskContext.getMessageService());
+ TaskUtil.sendBarrier(taskContext.getSession(), cookie, taskContext.getMessageService());
Future<RpcResult<BarrierOutput>> barrierFuture = sendBarrierRpc.getOutput();
try {
RpcResult<BarrierOutput> barrierResult = barrierFuture.get(
return errors;
}
- /**
- * @param session
- * @param cookie
- * @param messageService
- * @return barrier response
- */
- protected static RpcInputOutputTuple<BarrierInput, ListenableFuture<RpcResult<BarrierOutput>>> sendBarrier(SessionContext session,
- SwitchConnectionDistinguisher cookie, IMessageDispatchService messageService) {
- BarrierInput barrierInput = MessageFactory.createBarrier(
- session.getFeatures().getVersion(), session.getNextXid());
- Future<RpcResult<BarrierOutput>> barrierResult = messageService.barrier(barrierInput, cookie);
- ListenableFuture<RpcResult<BarrierOutput>> output = JdkFutureAdapters.listenInPoolThread(barrierResult);
-
- return new RpcInputOutputTuple<>(barrierInput, output);
- }
-
/**
* @param task of rpc
* @param originalResult
@Override
public ListenableFuture<RpcResult<T>> apply(final RpcResult<T> input) throws Exception {
if (input.isSuccessful()) {
- RpcInputOutputTuple<BarrierInput, ListenableFuture<RpcResult<BarrierOutput>>> sendBarrierRpc = sendBarrier(
+ RpcInputOutputTuple<BarrierInput, ListenableFuture<RpcResult<BarrierOutput>>> sendBarrierRpc = TaskUtil.sendBarrier(
task.getSession(), task.getCookie(), task.getMessageService());
ListenableFuture<RpcResult<T>> barrierTxResult = Futures.transform(
sendBarrierRpc.getOutput(),
import org.opendaylight.openflowplugin.openflow.md.core.MDController;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManager;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManagerImpl;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.openflowplugin.api.statistics.MessageCountDumper;
import org.opendaylight.openflowplugin.api.statistics.MessageObservatory;
import org.opendaylight.openflowplugin.statistics.MessageSpyCounterImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
private ExtensionConverterManager extensionConverterManager;
+ private OfpRole role;
+
+ private OFRoleManager roleManager;
+
/**
* Initialization of services and msgSpy counter
*/
public void initialization() {
messageCountProvider = new MessageSpyCounterImpl();
extensionConverterManager = new ExtensionConverterManagerImpl();
+ roleManager = new OFRoleManager(OFSessionUtil.getSessionManager());
this.registerProvider();
}
public ExtensionConverterRegistrator getExtensionConverterRegistrator() {
return extensionConverterManager;
}
+
+ /**
+ * @param role of instance
+ */
+ public void setRole(OfpRole role) {
+ this.role = role;
+ }
+
+ /**
+ * @param newRole
+ */
+ public void fireRoleChange(OfpRole newRole) {
+ if (!role.equals(newRole)) {
+ LOG.debug("my role was chaged from {} to {}", role, newRole);
+ role = newRole;
+ switch (role) {
+ case BECOMEMASTER:
+ //TODO: implement appropriate action
+ roleManager.manageRoleChange(role);
+ break;
+ case BECOMESLAVE:
+ //TODO: implement appropriate action
+ roleManager.manageRoleChange(role);
+ break;
+ case NOCHANGE:
+ //TODO: implement appropriate action
+ roleManager.manageRoleChange(role);
+ break;
+ default:
+ LOG.warn("role not supported: {}", role);
+ break;
+ }
+ }
+ }
}
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import org.opendaylight.controller.sal.common.util.RpcErrors;
-import org.opendaylight.controller.sal.common.util.Rpcs;
+
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowplugin.ConnectionException;
-import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.util.RpcResultUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutputBuilder;
-import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.Future;
/**
public class MessageDispatchServiceImpl implements IMessageDispatchService {
private static final Logger LOG = LoggerFactory.getLogger(MessageDispatchServiceImpl.class);
- private static final String CONNECTION_ERROR_MESSAGE = "Session for the cookie is invalid. Reason: "
- + "the switch has been recently disconnected OR inventory provides outdated information.";
-
private SessionContext session;
/**
try {
return getConnectionAdapter(cookie).barrier(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
- private <T> SettableFuture<RpcResult<T>> getRpcErrorFuture(ConnectionException e) {
- List<RpcError> rpcErrorList = getConnectionErrorAsRpcErrors(e);
- SettableFuture<RpcResult<T>> futureWithError = SettableFuture.create();
- futureWithError.set(Rpcs.<T>getRpcResult(false, rpcErrorList));
- return futureWithError;
- }
-
- private List<RpcError> getConnectionErrorAsRpcErrors(ConnectionException e) {
- List<RpcError> rpcErrorList = new ArrayList<>();
- rpcErrorList.add(RpcErrors.getRpcError(OFConstants.APPLICATION_TAG,
- OFConstants.ERROR_TAG_TIMEOUT,
- CONNECTION_ERROR_MESSAGE,
- RpcError.ErrorSeverity.WARNING,
- e.getMessage(),
- RpcError.ErrorType.TRANSPORT,
- e.getCause()));
- return rpcErrorList;
- }
-
@Override
public Future<RpcResult<Void>> experimenter(ExperimenterInput input, SwitchConnectionDistinguisher cookie) {
try {
return getConnectionAdapter(cookie).experimenter(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
response = getConnectionAdapter(cookie).flowMod(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
// appending xid
flowModOutput.setTransactionId(new TransactionId(bigIntXid));
UpdateFlowOutput result = flowModOutput.build();
- RpcResult<UpdateFlowOutput> rpcResult = Rpcs.getRpcResult(
- inputArg.isSuccessful(), result, inputArg.getErrors());
+ RpcResult<UpdateFlowOutput> rpcResult = RpcResultBuilder
+ .<UpdateFlowOutput>status(inputArg.isSuccessful())
+ .withResult(result).withRpcErrors(inputArg.getErrors())
+ .build();
return rpcResult;
}
});
try {
return getConnectionAdapter(cookie).getAsync(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).getConfig(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).getFeatures(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).getQueueConfig(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
response = getConnectionAdapter(cookie).groupMod(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
// appending xid
groupModOutput.setTransactionId(new TransactionId(bigIntXid));
UpdateGroupOutput result = groupModOutput.build();
- RpcResult<UpdateGroupOutput> rpcResult = Rpcs.getRpcResult(
- inputArg.isSuccessful(), result, inputArg.getErrors());
+ RpcResult<UpdateGroupOutput> rpcResult = RpcResultBuilder
+ .<UpdateGroupOutput>status(inputArg.isSuccessful()).withResult(result)
+ .withRpcErrors(inputArg.getErrors()).build();
return rpcResult;
}
});
try {
response = getConnectionAdapter(cookie).meterMod(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
// appending xid
meterModOutput.setTransactionId(new TransactionId(bigIntXid));
UpdateMeterOutput result = meterModOutput.build();
- RpcResult<UpdateMeterOutput> rpcResult = Rpcs.getRpcResult(
- inputArg.isSuccessful(), result, inputArg.getErrors());
+ RpcResult<UpdateMeterOutput> rpcResult = RpcResultBuilder
+ .<UpdateMeterOutput>status(inputArg.isSuccessful()).withResult(result)
+ .withRpcErrors(inputArg.getErrors()).build();
return rpcResult;
}
});
try {
return getConnectionAdapter(cookie).multipartRequest(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).packetOut(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
response = getConnectionAdapter(cookie).portMod(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
// appending xid
portModOutput.setTransactionId(new TransactionId(bigIntXid));
UpdatePortOutput result = portModOutput.build();
- RpcResult<UpdatePortOutput> rpcResult = Rpcs.getRpcResult(
- inputArg.isSuccessful(), result, inputArg.getErrors());
+ RpcResult<UpdatePortOutput> rpcResult = RpcResultBuilder
+ .<UpdatePortOutput>status(inputArg.isSuccessful()).withResult(result)
+ .withRpcErrors(inputArg.getErrors()).build();
return rpcResult;
}
});
try {
return getConnectionAdapter(cookie).roleRequest(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).setAsync(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).setConfig(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
try {
return getConnectionAdapter(cookie).tableMod(input);
} catch (ConnectionException e) {
- return getRpcErrorFuture(e);
+ return RpcResultUtil.getRpcErrorFuture(e);
}
}
}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.core.session;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.math.BigInteger;
+import java.util.Comparator;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionManager;
+import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
+import org.opendaylight.openflowplugin.openflow.md.util.RoleUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * manage OF-role propagation to devices
+ */
+public class OFRoleManager implements AutoCloseable {
+
+ /**
+ * starting value of generationId
+ */
+ public static final BigInteger MAX_GENERATION_ID = new BigInteger("ffffffffffffffff", 16);
+
+ private static final Logger LOG = LoggerFactory.getLogger(OFRoleManager.class);
+
+ private static final long TIMEOUT = 2000;
+
+ private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
+
+ private static final int RETRY_LIMIT = 42;
+
+ private final ListeningExecutorService broadcastPool;
+
+ private final BlockingQueue<RolePushTask> workQueue;
+
+ private final SessionManager sessionManager;
+
+ /**
+ * @param sessionManager
+ */
+ public OFRoleManager(SessionManager sessionManager) {
+ Preconditions.checkNotNull("Session manager can not be empty.", sessionManager);
+ this.sessionManager = sessionManager;
+ workQueue = new PriorityBlockingQueue<>(500, new Comparator<RolePushTask>() {
+ @Override
+ public int compare(RolePushTask o1, RolePushTask o2) {
+ return Integer.compare(o1.getPriority(), o2.getPriority());
+ }
+ });
+ ThreadPoolLoggingExecutor delegate = new ThreadPoolLoggingExecutor(
+ 1, 1, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), "ofRoleBroadcast");
+ broadcastPool = MoreExecutors.listeningDecorator(
+ delegate);
+ }
+
+ /**
+ * change role on each connected device
+ *
+ * @param role
+ */
+ public void manageRoleChange(final OfpRole role) {
+ for (final SessionContext session : sessionManager.getAllSessions()) {
+ try {
+ workQueue.put(new RolePushTask(role, session));
+ } catch (InterruptedException e) {
+ LOG.warn("Processing of role request failed while enqueueing role task: {}", e.getMessage());
+ }
+ }
+
+ while (!workQueue.isEmpty()) {
+ RolePushTask task = workQueue.poll();
+ ListenableFuture<Boolean> rolePushResult = broadcastPool.submit(task);
+ CheckedFuture<Boolean, RolePushException> rolePushResultChecked =
+ RoleUtil.makeCheckedRuleRequestFxResult(rolePushResult);
+ try {
+ Boolean succeeded = rolePushResultChecked.checkedGet(TIMEOUT, TIMEOUT_UNIT);
+ if (!Objects.firstNonNull(succeeded, Boolean.FALSE)) {
+ if (task.getRetryCounter() < RETRY_LIMIT) {
+ workQueue.offer(task);
+ }
+ }
+ } catch (RolePushException | TimeoutException e) {
+ LOG.warn("failed to process role request: {}", e);
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ broadcastPool.shutdown();
+ }
+}
return getSessionManager().getExtensionConverterProvider();
}
+ /**
+ * @return collection of all sessions
+ */
+ public static Collection<SessionContext> getAllSessions() {
+ return getSessionManager().getAllSessions();
+ }
+
}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.core.session;
+
+/**
+ * covers role pushing issues
+ */
+public class RolePushException extends Exception {
+
+ private static final long serialVersionUID = -615991366447313972L;
+
+ /**
+ * default ctor
+ *
+ * @param message
+ */
+ public RolePushException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public RolePushException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.core.session;
+
+import com.google.common.base.Preconditions;
+import java.math.BigInteger;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.core.MessageFactory;
+import org.opendaylight.openflowplugin.openflow.md.util.RoleUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * push role to device - basic step:<br/>
+ * <ul>
+ * <li>here we read generationId from device and</li>
+ * <li>push role request with incremented generationId</li>
+ * <li>{@link #call()} returns true if role request was successful</li>
+ * </ul>
+ */
+final class RolePushTask implements Callable<Boolean> {
+
+ public static final Logger LOG = LoggerFactory
+ .getLogger(RolePushTask.class);
+
+ public static final long TIMEOUT = 2000;
+ public static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
+ private OfpRole role;
+ private SessionContext session;
+ private int priority;
+ private int retryCounter;
+
+ /**
+ * @param role
+ * @param session
+ */
+ public RolePushTask(OfpRole role, SessionContext session) {
+ Preconditions.checkNotNull("OfpRole can not be empty.", role);
+ Preconditions.checkNotNull("Session context can not be empty.", session);
+ this.role = role;
+ this.session = session;
+ }
+
+ /**
+ * @return the retryCounter
+ */
+ public int getRetryCounter() {
+ return retryCounter;
+ }
+
+ /**
+ * @return the priority
+ */
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * @param priority the priority to set
+ */
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ @Override
+ public Boolean call() throws RolePushException {
+ if (!session.isValid()) {
+ String msg = "giving up role change: current session is invalid";
+ LOG.debug(msg);
+ throw new RolePushException(msg);
+ }
+
+ // adopt actual generationId from device (first shot failed and this is retry)
+ BigInteger generationId = null;
+ try {
+ generationId = RoleUtil.readGenerationIdFromDevice(session).get(TIMEOUT, TIMEOUT_UNIT);
+ } catch (Exception e) {
+ LOG.debug("generationId request failed: ", e);
+ }
+
+ if (generationId == null) {
+ String msg = "giving up role change: current generationId can not be read";
+ LOG.debug(msg);
+ throw new RolePushException(msg);
+ }
+
+ generationId = RoleUtil.getNextGenerationId(generationId);
+
+ // try to possess role on device
+ Future<RpcResult<RoleRequestOutput>> roleReply = RoleUtil.sendRoleChangeRequest(session, role, generationId);
+ // flush election result with barrier
+ BarrierInput barrierInput = MessageFactory.createBarrier(
+ session.getFeatures().getVersion(), session.getNextXid());
+ Future<RpcResult<BarrierOutput>> barrierResult = session.getPrimaryConductor().getConnectionAdapter().barrier(barrierInput);
+ try {
+ barrierResult.get(TIMEOUT, TIMEOUT_UNIT);
+ } catch (Exception e) {
+ String msg = String.format("giving up role change: barrier after role change failed: %s", e.getMessage());
+ LOG.warn(msg);
+ throw new RolePushException(msg);
+ }
+ // after barrier replied there must be election result or error
+ try {
+ roleReply.get(0, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ // no election result received - let's retry
+ retryCounter += 1;
+ return false;
+ }
+
+ // here we expect that role on device is successfully possessed
+ return true;
+ }
+}
\ No newline at end of file
package org.opendaylight.openflowplugin.openflow.md.core.session;
+import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
-import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
-import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
-import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
import org.opendaylight.openflowplugin.api.openflow.md.ModelDrivenSwitch;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.openflowplugin.api.openflow.md.core.NotificationEnqueuer;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortGrouping;
import org.opendaylight.yangtools.concepts.CompositeObjectRegistration;
private final Map<Long, Boolean> portBandwidth;
private CompositeObjectRegistration<ModelDrivenSwitch> providerRegistration;
private int seed;
-
+ private ControllerRole roleOnDevice = ControllerRole.OFPCRROLEEQUAL;
+
/**
* default ctor
public Set<Entry<SwitchConnectionDistinguisher, ConnectionConductor>> getAuxiliaryConductors() {
return Collections.unmodifiableSet(auxiliaryConductors.entrySet());
}
-
+
@Override
public GetFeaturesOutput getFeatures() {
return features;
public void setSessionKey(SwitchSessionKeyOF sessionKey) {
this.sessionKey = sessionKey;
}
-
+
/**
* @param seed the seed to set
*/
public Map<Long, PortGrouping> getPhysicalPorts() {
return this.physicalPorts;
}
-
+
@Override
public Map<Long, Boolean> getPortsBandwidth() {
return this.portBandwidth;
}
return result;
}
-
+
@Override
public void setProviderRegistration(
CompositeObjectRegistration<ModelDrivenSwitch> providerRegistration) {
this.providerRegistration = providerRegistration;
}
-
+
@Override
public CompositeObjectRegistration<ModelDrivenSwitch> getProviderRegistration() {
return providerRegistration;
}
-
+
@Override
public int getSeed() {
return seed;
}
-
+
/**
* @param notificationEnqueuer the notificationEnqueuer to set
*/
NotificationEnqueuer notificationEnqueuer) {
this.notificationEnqueuer = notificationEnqueuer;
}
-
+
@Override
public NotificationEnqueuer getNotificationEnqueuer() {
return notificationEnqueuer;
}
+
+ /**
+ * @return the roleOnDevice
+ */
+ @Override
+ public ControllerRole getRoleOnDevice() {
+ return roleOnDevice;
+ }
+
+ /**
+ * @param roleOnDevice the roleOnDevice to set
+ */
+ @Override
+ public void setRoleOnDevice(ControllerRole roleOnDevice) {
+ Preconditions.checkNotNull("Proposed controller role can not be empty.", roleOnDevice);
+ this.roleOnDevice = roleOnDevice;
+ }
}
package org.opendaylight.openflowplugin.openflow.md.core.session;
import com.google.common.util.concurrent.ListeningExecutorService;
-
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
-
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionListener;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
+import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
import org.opendaylight.openflowplugin.api.statistics.MessageSpy;
-import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
-import org.opendaylight.openflowplugin.api.openflow.md.core.IMDMessageTranslator;
import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
-import org.opendaylight.openflowplugin.api.openflow.md.queue.PopListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.util.ListenerRegistry;
}
/**
- * close and release singleton instace
+ * close and release singleton instance
*/
public static void releaseInstance() {
if (instance != null) {
// TODO: handle timeouted shutdown
rpcPool.shutdown();
}
-
+
for (ListenerRegistration<SessionListener> listenerRegistration : sessionListeners) {
SessionListener listener = listenerRegistration.getInstance();
if (listener instanceof AutoCloseable) {
public ExtensionConverterProvider getExtensionConverterProvider() {
return extensionConverterProvider;
}
+
+ @Override
+ public Collection<SessionContext> getAllSessions() {
+ return sessionLot.values();
+ }
}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.util;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager;
+import org.opendaylight.openflowplugin.openflow.md.core.session.RolePushException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ */
+public final class RoleUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RoleUtil.class);
+ private static final Function<Exception, RolePushException> exceptionFunction = new Function<Exception, RolePushException>() {
+ @Override
+ public RolePushException apply(Exception input) {
+ RolePushException output = null;
+ if (input instanceof ExecutionException) {
+ if (input.getCause() instanceof RolePushException) {
+ output = (RolePushException) input.getCause();
+ }
+ }
+
+ if (output == null) {
+ output = new RolePushException(input.getMessage(), input);
+ }
+
+ return output;
+ }
+ };
+
+ private RoleUtil() {
+ throw new UnsupportedOperationException("RoleUtil is not expected to be instantiated.");
+ }
+
+ /**
+ * @param role
+ * @return protocol role
+ */
+ public static ControllerRole toOFJavaRole(OfpRole role) {
+ ControllerRole ofJavaRole = null;
+ switch (role) {
+ case BECOMEMASTER:
+ ofJavaRole = ControllerRole.OFPCRROLEMASTER;
+ break;
+ case BECOMESLAVE:
+ ofJavaRole = ControllerRole.OFPCRROLESLAVE;
+ break;
+ case NOCHANGE:
+ ofJavaRole = ControllerRole.OFPCRROLENOCHANGE;
+ break;
+ default:
+ // no intention
+ LOG.warn("given role is not supported by protocol roles: {}", role);
+ break;
+ }
+ return ofJavaRole;
+ }
+
+ /**
+ * @param session
+ * @param role
+ * @param generationId
+ * @return input builder
+ */
+ public static RoleRequestInputBuilder createRoleRequestInput(
+ final SessionContext session, OfpRole role, BigInteger generationId) {
+
+ ControllerRole ofJavaRole = RoleUtil.toOFJavaRole(role);
+
+ return new RoleRequestInputBuilder()
+ .setGenerationId(generationId)
+ .setRole(ofJavaRole)
+ .setVersion(session.getFeatures().getVersion())
+ .setXid(session.getNextXid());
+ }
+
+ /**
+ * @param sessionContext
+ * @param ofpRole
+ * @param generationId
+ * @return roleRequest future result
+ */
+ public static Future<RpcResult<RoleRequestOutput>> sendRoleChangeRequest(SessionContext sessionContext, OfpRole ofpRole, BigInteger generationId) {
+ RoleRequestInputBuilder ruleRequestInputBld = RoleUtil.createRoleRequestInput(sessionContext, ofpRole, generationId);
+ Future<RpcResult<RoleRequestOutput>> roleReply = sessionContext.getPrimaryConductor().getConnectionAdapter()
+ .roleRequest(ruleRequestInputBld.build());
+ return roleReply;
+ }
+
+ /**
+ * @param sessionContext
+ * @return generationId from future RpcResult
+ */
+ public static Future<BigInteger> readGenerationIdFromDevice(SessionContext sessionContext) {
+ Future<BigInteger> generationIdFuture = null;
+ Future<RpcResult<RoleRequestOutput>> roleReply = sendRoleChangeRequest(sessionContext, OfpRole.NOCHANGE, BigInteger.ZERO);
+ generationIdFuture = Futures.transform(
+ JdkFutureAdapters.listenInPoolThread(roleReply),
+ new Function<RpcResult<RoleRequestOutput>, BigInteger>() {
+ @Override
+ public BigInteger apply(RpcResult<RoleRequestOutput> input) {
+ return input.getResult().getGenerationId();
+ }
+ });
+
+ return generationIdFuture;
+ }
+
+ /**
+ * @param generationId
+ * @return next (incremented value)
+ */
+ public static BigInteger getNextGenerationId(BigInteger generationId) {
+ BigInteger nextGenerationId = null;
+ if (generationId.compareTo(OFRoleManager.MAX_GENERATION_ID) < 0) {
+ nextGenerationId = generationId.add(BigInteger.ONE);
+ } else {
+ nextGenerationId = BigInteger.ZERO;
+ }
+
+ return nextGenerationId;
+ }
+
+ /**
+ * @param rolePushResult
+ * @return future which throws {@link RolePushException}
+ */
+ public static CheckedFuture<Boolean, RolePushException> makeCheckedRuleRequestFxResult(
+ ListenableFuture<Boolean> rolePushResult) {
+ return Futures.makeChecked(
+ rolePushResult, exceptionFunction
+ );
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.util;
+
+import com.google.common.util.concurrent.SettableFuture;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.openflowplugin.ConnectionException;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ *
+ */
+public final class RpcResultUtil {
+
+ private RpcResultUtil() {
+ throw new UnsupportedOperationException("RpcResultUtil is not expected to be instantiated.");
+ }
+
+ /**
+ * @param e
+ * @return error wrapped inside {@link RpcResult} which is wrapped inside future
+ */
+ public static <T> SettableFuture<RpcResult<T>> getRpcErrorFuture(ConnectionException e) {
+ List<RpcError> rpcErrorList = wrapConnectionErrorIntoRpcErrors(e);
+ SettableFuture<RpcResult<T>> futureWithError = SettableFuture.create();
+ futureWithError.set(RpcResultBuilder.<T>failed().withRpcErrors(rpcErrorList).build());
+ return futureWithError;
+ }
+
+ private static List<RpcError> wrapConnectionErrorIntoRpcErrors(ConnectionException e) {
+ List<RpcError> rpcErrorList = new ArrayList<>();
+ rpcErrorList.add(RpcResultBuilder.newError(
+ RpcError.ErrorType.TRANSPORT,
+ OFConstants.ERROR_TAG_TIMEOUT,
+ e.getMessage(),
+ OFConstants.APPLICATION_TAG,
+ IMessageDispatchService.CONNECTION_ERROR_MESSAGE,
+ e.getCause()));
+ return rpcErrorList;
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.util;
+
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.IMessageDispatchService;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.core.MessageFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+/**
+ *
+ */
+public final class TaskUtil {
+
+ private TaskUtil() {
+ throw new AssertionError("TaskUtil is not expected to be instantiated.");
+ }
+
+ /**
+ * @param session
+ * @param cookie
+ * @param messageService
+ * @return barrier response
+ */
+ public static RpcInputOutputTuple<BarrierInput, ListenableFuture<RpcResult<BarrierOutput>>> sendBarrier(SessionContext session,
+ SwitchConnectionDistinguisher cookie, IMessageDispatchService messageService) {
+ BarrierInput barrierInput = MessageFactory.createBarrier(
+ session.getFeatures().getVersion(), session.getNextXid());
+ Future<RpcResult<BarrierOutput>> barrierResult = messageService.barrier(barrierInput, cookie);
+ ListenableFuture<RpcResult<BarrierOutput>> output = JdkFutureAdapters.listenInPoolThread(barrierResult);
+
+ return new RpcInputOutputTuple<>(barrierInput, output);
+ }
+
+
+}
*/
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326;
+import javax.management.ObjectName;
+
import org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider;
+import com.google.common.base.MoreObjects;
+
/**
*
*/
pluginProvider = new OpenflowPluginProvider();
pluginProvider.setBroker(getBindingAwareBrokerDependency());
pluginProvider.setSwitchConnectionProviders(getOpenflowSwitchConnectionProviderDependency());
+ pluginProvider.setRole(getRole());
pluginProvider.initialization();
return pluginProvider;
}
+
+ @Override
+ public boolean canReuseInstance(
+ AbstractConfigurableOpenFlowProviderModule oldModule) {
+ // we can reuse if only the role field changed
+ boolean noChangeExceptRole = true;
+ noChangeExceptRole &= dependencyResolver.canReuseDependency(
+ getBindingAwareBroker(), bindingAwareBrokerJmxAttribute);
+ for (ObjectName ofSwitchProvider : getOpenflowSwitchConnectionProvider()) {
+ noChangeExceptRole &= dependencyResolver.canReuseDependency(
+ ofSwitchProvider, openflowSwitchConnectionProviderJmxAttribute);
+ }
+ return noChangeExceptRole;
+ }
+
+ @Override
+ public AutoCloseable reuseInstance(AutoCloseable oldInstance) {
+ OpenflowPluginProvider recycled = (OpenflowPluginProvider) super.reuseInstance(oldInstance);
+ // change role if different
+ recycled.fireRoleChange(MoreObjects.firstNonNull(getRole(), getRole()));
+
+ return recycled;
+ }
}
config:java-name-prefix MsgSpyService;
}
+ // role of OFPlugin instance
+ typedef ofp-role {
+ type enumeration {
+ enum NOCHANGE {
+ description "no change to role";
+ }
+ enum BECOMEMASTER {
+ description "promote current role to MASTER";
+ }
+ enum BECOMESLAVE {
+ description "demote current role to SLAVE";
+ }
+ }
+ }
+
augment "/config:modules/config:module/config:configuration" {
case openflow-provider-impl {
when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
}
}
}
+ leaf role {
+ type ofp-role;
+ default "NOCHANGE";
+ }
}
case msg-spy-service-impl {
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.controller.sal.common.util.Futures;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.Elements;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.hello.ElementsBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
/**
* testing handshake
*/
@RunWith(MockitoJUnitRunner.class)
public class HandshakeManagerImplTest {
-
+
private static final Logger LOG = LoggerFactory
.getLogger(HandshakeManagerImplTest.class);
-
+
private HandshakeManagerImpl handshakeManager;
@Mock
private ConnectionAdapter adapter;
private long helloXid = 42L;
private int expectedErrors = 0;
-
+
/**
* invoked before every test method
*/
handshakeManager.setErrorHandler(errorHandler);
handshakeManager.setHandshakeListener(handshakeListener);
handshakeManager.setUseVersionBitmap(false);
-
- resultFeatures = RpcResultsUtil.createRpcResult(true, new GetFeaturesOutputBuilder().build(), null);
-
+
+ resultFeatures = RpcResultBuilder.success(new GetFeaturesOutputBuilder().build()).build();
+
Mockito.when(adapter.hello(Matchers.any(HelloInput.class)))
- .thenReturn(Futures.immediateFuture(RpcResultsUtil.createRpcResult(true, (Void) null, null)));
+ .thenReturn(Futures.immediateFuture(
+ RpcResultBuilder.success((Void) null).build()));
}
-
+
/**
* invoked after each test method
*/
for (Throwable problem : errorCaptor.getAllValues()) {
LOG.warn(problem.getMessage(), problem);
}
-
+
Mockito.verify(errorHandler, Mockito.times(expectedErrors)).handleException(
Matchers.any(Throwable.class), Matchers.any(SessionContext.class));
}
{true, true, true, false, false, false},
{true, true, true, false, false}
};
-
+
for (Boolean[] verasionList : versions) {
ElementsBuilder elementsBuilder = new ElementsBuilder();
elementsBuilder.setVersionBitmap(Lists.newArrayList(verasionList));
}
//////// Version Negotiation Tests //////////////
-
+
/**
* Test of version negotiation Where switch version = 1.0
*
public void testVersionNegotiation10() throws Exception {
LOG.debug("testVersionNegotiation10");
Short version = OFConstants.OFP_VERSION_1_0;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(resultFeatures.getResult(), version);
}
-
+
/**
* Test of version negotiation Where switch version = 1.0
*
public void testVersionNegotiation10SwitchStarts() throws Exception {
LOG.debug("testVersionNegotiation10-ss");
Short version = OFConstants.OFP_VERSION_1_0;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(resultFeatures.getResult(), version);
}
LOG.debug("testVersionNegotiation00");
expectedErrors = 1;
Short version = (short) 0x00;
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
}
-
+
/**
* Test of version negotiation Where switch version < 1.0
* Switch delivers first helloMessage with version 0x00 = negotiation unsuccessful
LOG.debug("testVersionNegotiation00-ss");
expectedErrors = 1;
Short version = (short) 0x00;
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
}
LOG.debug("testVersionNegotiation11");
Short version = (short) 0x02;
Short expVersion = (short) 0x01;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), expVersion);
}
-
+
/**
* Test of version negotiation Where 1.0 < switch version < 1.3
*
LOG.debug("testVersionNegotiation11-ss");
Short version = (short) 0x02;
Short expVersion = (short) 0x01;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), expVersion);
}
public void testVersionNegotiation13() throws Exception {
LOG.debug("testVersionNegotiation13");
Short version = OFConstants.OFP_VERSION_1_3;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), version);
}
-
+
/**
* Test of version negotiation Where switch version = 1.3
*
public void testVersionNegotiation13SwitchStarts() throws Exception {
LOG.debug("testVersionNegotiation13-ss");
Short version = OFConstants.OFP_VERSION_1_3;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), version);
}
LOG.debug("testVersionNegotiation15");
Short version = (short) 0x06;
Short expVersion = OFConstants.OFP_VERSION_1_3;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), expVersion);
}
-
+
/**
* Test of version negotiation Where switch version >= 1.3
*
LOG.debug("testVersionNegotiation15-ss");
Short version = (short) 0x06;
Short expVersion = OFConstants.OFP_VERSION_1_3;
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(expVersion, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), expVersion);
}
LOG.debug("testVersionNegotiation15_MultipleCall");
Short version = (short) 0x06;
expectedErrors = 1;
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
}
-
+
/**
* Test of version negotiation Where switch version > 1.3
*
LOG.debug("testVersionNegotiation15_MultipleCall-ss");
Short version = (short) 0x06;
expectedErrors = 1;
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(createHelloMessage(version, helloXid).build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
}
HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_0), helloMessage);
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(helloMessage.build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), version);
}
-
+
/**
* Test of version negotiation Where bitmap version {0x05,0x01}
*
HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_0), helloMessage);
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(helloMessage.build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), version);
}
HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_3), helloMessage);
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.setReceivedHello(helloMessage.build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), version);
}
-
+
/**
* Test of version negotiation Where bitmap version {0x05,0x04}
*
HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
addVersionBitmap(Lists.newArrayList((short) 0x05, OFConstants.OFP_VERSION_1_3), helloMessage);
-
+
Mockito.when(adapter.getFeatures(Matchers.any(GetFeaturesInput.class)))
.thenReturn(Futures.immediateFuture(resultFeatures));
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(helloMessage.build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener).onHandshakeSuccessfull(
resultFeatures.getResult(), version);
}
Short version = (short) 0x05;
expectedErrors = 1;
handshakeManager.setUseVersionBitmap(true);
-
+
HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
addVersionBitmap(Lists.newArrayList((short) 0x05, (short) 0x02), helloMessage);
-
+
handshakeManager.setReceivedHello(helloMessage.build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
}
-
+
/**
* Test of version negotiation Where bitmap version {0x05,0x02}
*
Short version = (short) 0x05;
expectedErrors = 1;
handshakeManager.setUseVersionBitmap(true);
-
+
HelloMessageBuilder helloMessage = createHelloMessage(version, helloXid);
addVersionBitmap(Lists.newArrayList((short) 0x05, (short) 0x02), helloMessage);
-
+
handshakeManager.shake();
-
+
handshakeManager.setReceivedHello(helloMessage.build());
handshakeManager.shake();
-
+
Mockito.verify(handshakeListener, Mockito.never()).onHandshakeSuccessfull(
Matchers.any(GetFeaturesOutput.class), Matchers.anyShort());
}
private static HelloMessageBuilder createHelloMessage(short ofpVersion10, long helloXid) {
return new HelloMessageBuilder().setVersion(ofpVersion10).setXid(helloXid);
}
-
+
/**
* @param versionOrder
* @param helloBuilder
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.core;
-
-import java.util.Collection;
-import java.util.Collections;
-import org.opendaylight.controller.sal.common.util.Rpcs;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-
-/**
- * Created by Martin Bobak mbobak@cisco.com on 8/25/14.
- */
-public class RpcResultsUtil {
-
- /**
- * @param success
- * @param result
- * @param errors
- * @return
- */
- public static <T> RpcResult<T> createRpcResult(boolean success, T result, Collection<RpcError> errorsArg) {
- Collection<RpcError> errors = errorsArg;
- if (errors == null) {
- errors = Collections.emptyList();
- }
- return Rpcs.getRpcResult(success, result, errors);
- }
-
-}
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.junit.Assert;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
import org.opendaylight.openflowplugin.api.openflow.md.core.session.SwitchSessionKeyOF;
import org.opendaylight.openflowplugin.api.openflow.md.queue.QueueProcessor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
* Test get async input with null cookie
*/
@Test
- public void testGetAsync() throws ExecutionException, InterruptedException {
+ public void testGetAsync() {
MockConnectionConductor conductor = new MockConnectionConductor(1);
SwitchConnectionDistinguisher cookie = conductor.getAuxiliaryKey();
GetAsyncInputBuilder getAsyncInputBuilder = new GetAsyncInputBuilder();
MockSessionContext(int conductorNum) {
conductor = new MockConnectionConductor(conductorNum);
- map = new HashMap<SwitchConnectionDistinguisher, ConnectionConductor>();
+ map = new HashMap<>();
messageService = new MessageDispatchServiceImpl(this);
sessionKey = new SwitchSessionKeyOF();
sessionKey.setDatapathId(new BigInteger("0"));
public NotificationEnqueuer getNotificationEnqueuer() {
return conductor;
}
+
+ @Override
+ public ControllerRole getRoleOnDevice() {
+ return null;
+ }
+
+ @Override
+ public void setRoleOnDevice(ControllerRole roleOnDevice) {
+ // NOOP
+ }
}
class MockConnectionConductor implements ConnectionConductor,
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.core.session;
+
+import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ *
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class OFRoleManagerTest {
+
+ @Mock
+ private SessionManager sessionManager;
+ @Mock
+ private SessionContext session;
+ @Mock
+ private GetFeaturesOutput features;
+ @Mock
+ private ConnectionConductor primaryConductor;
+ @Mock
+ private ConnectionAdapter connectionAdapter;
+
+ private OFRoleManager manager;
+ private RoleRequestOutput roleRequestOutput;
+ private BarrierOutput barrierOutput;
+ private BigInteger generationId = BigInteger.TEN;
+
+ /**
+ * prepare values
+ */
+ @Before
+ public void setUp() {
+ Mockito.when(session.getFeatures()).thenReturn(features);
+ Mockito.when(features.getVersion()).thenReturn(Short.valueOf((short) 42));
+ Mockito.when(session.getNextXid()).thenReturn(84L);
+ Mockito.when(session.getPrimaryConductor()).thenReturn(primaryConductor);
+ Mockito.when(primaryConductor.getConnectionAdapter()).thenReturn(connectionAdapter);
+ roleRequestOutput = new RoleRequestOutputBuilder()
+ .setGenerationId(generationId)
+ .setRole(ControllerRole.OFPCRROLESLAVE)
+ .setVersion((short) 42)
+ .setXid(21L)
+ .build();
+ barrierOutput = new BarrierOutputBuilder()
+ .setVersion((short) 42)
+ .setXid(1L)
+ .build();
+
+ manager = new OFRoleManager(sessionManager);
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager#manageRoleChange(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole)}.
+ * <br/>
+ * session lot is empty is invalid
+ */
+ @Test
+ public void testManageRoleChangeFail1() {
+ manager.manageRoleChange(OfpRole.BECOMESLAVE);
+ Mockito.verify(connectionAdapter, Mockito.never()).roleRequest(Matchers.any(RoleRequestInput.class));
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager#manageRoleChange(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole)}.
+ * <br/>
+ * available session is invalid
+ */
+ @Test
+ public void testManageRoleChangeFail2() {
+ Mockito.when(sessionManager.getAllSessions()).thenReturn(Collections.singleton(session));
+ manager.manageRoleChange(OfpRole.BECOMESLAVE);
+ Mockito.verify(connectionAdapter, Mockito.never()).roleRequest(Matchers.any(RoleRequestInput.class));
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager#manageRoleChange(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole)}.
+ * <br/>
+ * device bound to valid session is not answering
+ */
+ @Test
+ public void testManageRoleChangeFail3() {
+ Mockito.when(session.isValid()).thenReturn(true);
+ Mockito.when(sessionManager.getAllSessions()).thenReturn(Collections.singleton(session));
+ manager.manageRoleChange(OfpRole.BECOMESLAVE);
+ Mockito.verify(connectionAdapter, Mockito.times(1)).roleRequest(Matchers.any(RoleRequestInput.class));
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager#manageRoleChange(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole)}.
+ */
+ @Test
+ public void testManageRoleChangeOK() {
+ Mockito.when(session.isValid()).thenReturn(true);
+ Mockito.when(sessionManager.getAllSessions()).thenReturn(Collections.singleton(session));
+ Mockito.when(connectionAdapter.roleRequest(Matchers.any(RoleRequestInput.class)))
+ .thenReturn(Futures.immediateFuture(RpcResultBuilder.success(roleRequestOutput).build()));
+ Mockito.when(connectionAdapter.barrier(Matchers.any(BarrierInput.class)))
+ .thenReturn(Futures.immediateFuture(RpcResultBuilder.success(barrierOutput).build()));
+
+ manager.manageRoleChange(OfpRole.BECOMESLAVE);
+
+ ArgumentCaptor<RoleRequestInput> roleRequestCaptor = ArgumentCaptor.forClass(RoleRequestInput.class);
+ Mockito.verify(connectionAdapter, Mockito.times(2)).roleRequest(roleRequestCaptor.capture());
+
+ List<RoleRequestInput> values = roleRequestCaptor.getAllValues();
+ Assert.assertEquals(ControllerRole.OFPCRROLENOCHANGE, values.get(0).getRole());
+ Assert.assertEquals(0L, values.get(0).getGenerationId().longValue());
+ Assert.assertEquals(ControllerRole.OFPCRROLESLAVE, values.get(1).getRole());
+ Assert.assertEquals(11L, values.get(1).getGenerationId().longValue());
+ }
+}
import java.util.HashMap;\r
import java.util.List;\r
import java.util.Map;\r
-\r
import org.junit.Assert;\r
import org.junit.Before;\r
import org.junit.Test;\r
* Created by Jakub Toth jatoth@cisco.com on 3/10/14.\r
*/\r
@RunWith(MockitoJUnitRunner.class)\r
-public class PacketInV10TranslatorTest{\r
+public class PacketInV10TranslatorTest {\r
private static final Logger LOG = LoggerFactory\r
.getLogger(PacketInV10TranslatorTest.class);\r
- \r
+\r
@Mock\r
private SessionContext sc;\r
@Mock\r
\r
private SwitchConnectionDistinguisher cookie;\r
private byte[] data;\r
- \r
+\r
/**\r
* Initializes mocks\r
*/\r
when(sc.getFeatures()).thenReturn(features);\r
when(features.getDatapathId()).thenReturn(new BigInteger("42"));\r
OpenflowPortsUtil.init();\r
- \r
+\r
cookie = settingCookie();\r
data = messageData();\r
}\r
- \r
+\r
/**\r
* test\r
* {@link PacketInV10Translator#translate(SwitchConnectionDistinguisher, SessionContext, OfHeader)}\r
* MD-SAL model, supports OF-1.0\r
*/\r
@Test\r
- public void testTranslateWithAllNullParam(){\r
+ public void testTranslateWithAllNullParam() {\r
SwitchConnectionDistinguisher cookieNull = null;\r
SessionContext sessionContext = null;\r
OfHeader msg = null;\r
* supports OF-1.0\r
*/\r
@Test\r
- public void testTranslateDPIDNull(){\r
- SessionContextOFImpl sessionContextOFImpl = new SessionContextOFImpl();\r
+ public void testTranslateDPIDNull() {\r
+ SessionContext sessionContextOFImpl = new SessionContextOFImpl();\r
\r
PacketInMessage message = createPacketInMessage(data, null);\r
\r
* supports OF-1.0\r
*/\r
@Test\r
- public void testTranslateInPortNull(){\r
+ public void testTranslateInPortNull() {\r
BigInteger datapathId = dataPathId();\r
\r
GetFeaturesOutputBuilder featuresBuilder = new GetFeaturesOutputBuilder();\r
* test\r
* {@link PacketInV10Translator#translate(SwitchConnectionDistinguisher, SessionContext, OfHeader)}\r
* - translates packetIn from OF-API model to MD-SAL model, supports OF-1.0\r
- * \r
+ *\r
* @throws IOException\r
*/\r
@Test\r
- public void testTranslate(){\r
+ public void testTranslate() {\r
BigInteger datapathId = dataPathId();\r
\r
PacketInMessage message = createPacketInMessage(data, 5);\r
OpenflowPortsUtil.init();\r
List<DataObject> salPacketIn = packetInV10Translator.translate(cookie,\r
sessionContextOFImpl, message);\r
- \r
+\r
//TODO: rewrite to object and involve object comparison in Assert\r
String expectedString = "[PacketReceived [_ingress=NodeConnectorRef [_value=KeyedInstanceIdentifier"\r
+ "{targetType=interface org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector,"\r
\r
/**\r
* create datapathID\r
- * \r
+ *\r
* @return BigInteger\r
*/\r
- private static BigInteger dataPathId(){\r
+ private static BigInteger dataPathId() {\r
byte[] datapathIdByte = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];\r
- for(int i = 0; i < datapathIdByte.length; i++){\r
+ for (int i = 0; i < datapathIdByte.length; i++) {\r
datapathIdByte[i] = 1;\r
}\r
return new BigInteger(1, datapathIdByte);\r
\r
/**\r
* generate message from string to byte[]\r
- * \r
+ *\r
* @return byte[]\r
*/\r
- private static byte[] messageData(){\r
+ private static byte[] messageData() {\r
String string = new String("sendOutputMsg_TEST");\r
return string.getBytes();\r
}\r
\r
/**\r
* create PacketInMessage with setting Version, InPort, Data, Reason\r
- * \r
+ *\r
* @param data\r
* @param port\r
* @return PacketInMessage\r
*/\r
private static PacketInMessage createPacketInMessage(final byte[] data,\r
- final java.lang.Integer port){\r
+ final java.lang.Integer port) {\r
PacketInReason reason = PacketInReason.OFPRACTION;\r
return new PacketInMessageBuilder()\r
.setVersion((short) EncodeConstants.OF10_VERSION_ID)\r
\r
/**\r
* create cookie\r
- * \r
+ *\r
* @return SwitchConnectionDistinguisher\r
*/\r
- private static SwitchConnectionDistinguisher settingCookie(){\r
+ private static SwitchConnectionDistinguisher settingCookie() {\r
SwitchConnectionCookieOFImpl key = new SwitchConnectionCookieOFImpl();\r
key.setAuxiliaryId((short) 1);\r
key.init(42);\r
\r
/**\r
* create GetFeatureOutput\r
- * \r
+ *\r
* @param datapathId\r
* @return GetFeaturesOutput\r
*/\r
- private static GetFeaturesOutput createGetFeatureOutput(final BigInteger datapathId){\r
+ private static GetFeaturesOutput createGetFeatureOutput(final BigInteger datapathId) {\r
return new GetFeaturesOutputBuilder().setDatapathId(datapathId)\r
.setVersion((short) 0x01).build();\r
}\r
\r
/**\r
* init connectionConductor\r
- * \r
+ *\r
* @param connectionConductor\r
* @param featuresOutput\r
*/\r
private static void initConnectionConductor(\r
final ConnectionConductorImpl connectionConductor,\r
- final GetFeaturesOutput featuresOutput){\r
+ final GetFeaturesOutput featuresOutput) {\r
TranslatorKey paramK = new TranslatorKey(1, PacketInMessage.class.getSimpleName());\r
Collection<IMDMessageTranslator<OfHeader, List<DataObject>>> coll = new ArrayList<>();\r
coll.add(new PacketInV10Translator());\r
--- /dev/null
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. 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.openflowplugin.openflow.md.util;
+
+import java.math.BigInteger;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import org.opendaylight.openflowplugin.api.openflow.md.core.ConnectionConductor;
+import org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext;
+import org.opendaylight.openflowplugin.openflow.md.core.session.OFRoleManager;
+import org.opendaylight.openflowplugin.openflow.md.core.session.RolePushException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import com.google.common.util.concurrent.Futures;
+
+/**
+ * testing {@link RoleUtil}
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class RoleUtilTest {
+
+ @Mock
+ private SessionContext session;
+ @Mock
+ private GetFeaturesOutput features;
+ @Mock
+ private ConnectionConductor primaryConductor;
+ @Mock
+ private ConnectionAdapter connectionAdapter;
+
+ private final BigInteger generationId = BigInteger.TEN;
+ private RoleRequestOutput roleRequestOutput;
+
+ /**
+ * prepare values
+ */
+ @Before
+ public void setUp() {
+ Mockito.when(session.getFeatures()).thenReturn(features);
+ Mockito.when(features.getVersion()).thenReturn(Short.valueOf((short) 42));
+ Mockito.when(session.getNextXid()).thenReturn(84L);
+ Mockito.when(session.getPrimaryConductor()).thenReturn(primaryConductor);
+ Mockito.when(primaryConductor.getConnectionAdapter()).thenReturn(connectionAdapter);
+ roleRequestOutput = new RoleRequestOutputBuilder()
+ .setGenerationId(generationId)
+ .setRole(ControllerRole.OFPCRROLESLAVE)
+ .setVersion((short) 42)
+ .setXid(21L)
+ .build();
+ Mockito.when(connectionAdapter.roleRequest(Matchers.any(RoleRequestInput.class)))
+ .thenReturn(Futures.immediateFuture(RpcResultBuilder.success(roleRequestOutput).build()));
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#toOFJavaRole(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole)}.
+ */
+ @Test
+ public void testToOFJavaRole() {
+ Assert.assertEquals(ControllerRole.OFPCRROLEMASTER, RoleUtil.toOFJavaRole(OfpRole.BECOMEMASTER));
+ Assert.assertEquals(ControllerRole.OFPCRROLESLAVE, RoleUtil.toOFJavaRole(OfpRole.BECOMESLAVE));
+ Assert.assertEquals(ControllerRole.OFPCRROLENOCHANGE, RoleUtil.toOFJavaRole(OfpRole.NOCHANGE));
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#toOFJavaRole(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole)}.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testToOFJavaRoleNull() {
+ RoleUtil.toOFJavaRole(null);
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#createRoleRequestInput(org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole, java.math.BigInteger)}.
+ */
+ @Test
+ public void testCreateRuleRequestInput() {
+ RoleRequestInput roleRequestInput = RoleUtil.createRoleRequestInput(session, OfpRole.BECOMEMASTER, generationId).build();
+ Assert.assertEquals(generationId, roleRequestInput.getGenerationId());
+ Assert.assertEquals(RoleRequestInput.class, roleRequestInput.getImplementedInterface());
+ Assert.assertEquals(ControllerRole.OFPCRROLEMASTER, roleRequestInput.getRole());
+ Assert.assertEquals(42, roleRequestInput.getVersion().intValue());
+ Assert.assertEquals(84L, roleRequestInput.getXid().longValue());
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#sendRoleChangeRequest(org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.common.config.impl.rev140326.OfpRole, java.math.BigInteger)}.
+ * @throws Exception
+ */
+ @Test
+ public void testSendRoleChangeRequest() throws Exception {
+ Future<RpcResult<RoleRequestOutput>> roleRequestOutputFx = RoleUtil.sendRoleChangeRequest(session, OfpRole.BECOMEMASTER, generationId);
+ Assert.assertNotNull(roleRequestOutputFx);
+
+ ArgumentCaptor<RoleRequestInput> roleRequestCaptor = ArgumentCaptor.forClass(RoleRequestInput.class);
+ Mockito.verify(connectionAdapter).roleRequest(roleRequestCaptor.capture());
+
+ RoleRequest roleRequestInput = roleRequestCaptor.getValue();
+ Assert.assertEquals(generationId, roleRequestInput.getGenerationId());
+ Assert.assertEquals(RoleRequestInput.class, roleRequestInput.getImplementedInterface());
+ Assert.assertEquals(ControllerRole.OFPCRROLEMASTER, roleRequestInput.getRole());
+ Assert.assertEquals(42, roleRequestInput.getVersion().intValue());
+ Assert.assertEquals(84L, roleRequestInput.getXid().longValue());
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#readGenerationIdFromDevice(org.opendaylight.openflowplugin.api.openflow.md.core.session.SessionContext)}.
+ * @throws Exception
+ */
+ @Test
+ public void testReadGenerationIdFromDevice() throws Exception {
+ BigInteger generationIdFromDevice = RoleUtil.readGenerationIdFromDevice(session).get();
+ Assert.assertEquals(generationId, generationIdFromDevice);
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#getNextGenerationId(java.math.BigInteger)}.
+ */
+ @Test
+ public void testGetNextGenerationId() {
+ BigInteger[] src = new BigInteger[] {
+ BigInteger.ZERO,
+ BigInteger.ONE,
+ OFRoleManager.MAX_GENERATION_ID.subtract(BigInteger.ONE),
+ OFRoleManager.MAX_GENERATION_ID
+ };
+
+ BigInteger[] out = new BigInteger[] {
+ BigInteger.ONE,
+ BigInteger.valueOf(2L),
+ OFRoleManager.MAX_GENERATION_ID,
+ BigInteger.ZERO
+ };
+
+ for (int i = 0; i < src.length; i++) {
+ BigInteger nextGenerationId = RoleUtil.getNextGenerationId(src[i]);
+ Assert.assertEquals(out[i], nextGenerationId);
+ }
+ }
+
+ /**
+ * Test method for {@link org.opendaylight.openflowplugin.openflow.md.util.RoleUtil#makeCheckedRuleRequestFxResult(com.google.common.util.concurrent.ListenableFuture)}.
+ * @throws Exception
+ */
+ @Test
+ public void testMakeCheckedRuleRequestFxResult() throws Exception {
+ String message = "me sooo naughty!";
+ try {
+ RoleUtil.makeCheckedRuleRequestFxResult(Futures.<Boolean>immediateFailedFuture(new Exception(message))).checkedGet();
+ } catch (Exception e) {
+ Assert.assertEquals(RolePushException.class, e.getClass());
+ Assert.assertEquals(ExecutionException.class, e.getCause().getClass());
+ Assert.assertEquals(Exception.class, e.getCause().getCause().getClass());
+ Assert.assertNull(e.getCause().getCause().getCause());
+ Assert.assertEquals(message, e.getCause().getCause().getMessage());
+ }
+
+ try {
+ RoleUtil.makeCheckedRuleRequestFxResult(Futures.<Boolean>immediateFailedFuture(new RolePushException(message))).checkedGet();
+ } catch (Exception e) {
+ Assert.assertEquals(RolePushException.class, e.getClass());
+ Assert.assertNull(e.getCause());
+ Assert.assertEquals(message, e.getMessage());
+ }
+
+ }
+}
<properties>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
<mdsal.version>1.2.0-SNAPSHOT</mdsal.version>
+ <netconf.version>1.2.0-SNAPSHOT</netconf.version>
<nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
<openflowjava.version>0.6.0-SNAPSHOT</openflowjava.version>
<openflowplugin.model.version>${project.version}</openflowplugin.model.version>
<artifactId>yang-binding</artifactId>
<version>${yang.binding.version}</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yang-common</artifactId>
- <version>${yang.binding.version}</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.yangtools.model</groupId>
- <artifactId>ietf-inet-types</artifactId>
- <version>${ietf-inet-types.version}</version>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ <version>${yang.binding.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
</dependency>
<dependency>
- <groupId>org.opendaylight.yangtools.model</groupId>
- <artifactId>ietf-yang-types</artifactId>
- <version>${ietf-yang-types.version}</version>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ <version>${ietf-inet-types.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ <version>${ietf-yang-types.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools.model</groupId>