--- /dev/null
+/*
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.impl.services;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.Futures;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Future;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
+import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.openflowplugin.extension.api.exception.ConversionException;
+import org.opendaylight.openflowplugin.extension.api.exception.ConverterNotFoundException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+public class SalExperimenterMpMessageServiceImpl extends AbstractMultipartService<SendExperimenterMpRequestInput> implements SalExperimenterMpMessageService {
+ private final ExtensionConverterProvider extensionConverterProvider;
+
+ public SalExperimenterMpMessageServiceImpl(final RequestContextStack requestContextStack,
+ final DeviceContext deviceContext,
+ final ExtensionConverterProvider extensionConverterProvider) {
+ super(requestContextStack, deviceContext);
+ this.extensionConverterProvider = extensionConverterProvider;
+ }
+
+ @Override
+ public Future<RpcResult<SendExperimenterMpRequestOutput>> sendExperimenterMpRequest(SendExperimenterMpRequestInput input) {
+ return Futures.lazyTransform(handleServiceCall(input), new Function<RpcResult<List<MultipartReply>>, RpcResult<SendExperimenterMpRequestOutput>>() {
+ @Nullable
+ @Override
+ public RpcResult<SendExperimenterMpRequestOutput> apply(final RpcResult<List<MultipartReply>> result) {
+ return result.isSuccessful()
+ ? RpcResultBuilder
+ .success(new SendExperimenterMpRequestOutputBuilder()
+ .setExperimenterMessageOfChoice(input.getExperimenterMessageOfChoice()))
+ .build()
+ : RpcResultBuilder
+ .<SendExperimenterMpRequestOutput>failed()
+ .withRpcErrors(result.getErrors())
+ .build();
+ }
+ });
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected OfHeader buildRequest(Xid xid, SendExperimenterMpRequestInput input) throws ServiceException {
+ final TypeVersionKey key = new TypeVersionKey(
+ input.getExperimenterMessageOfChoice().getImplementedInterface(),
+ getVersion());
+
+ final ConvertorMessageToOFJava<ExperimenterMessageOfChoice, ExperimenterDataOfChoice> messageConverter =
+ extensionConverterProvider.getMessageConverter(key);
+
+ if (Objects.isNull(messageConverter)) {
+ throw new ServiceException(new ConverterNotFoundException(key.toString()));
+ }
+
+ try {
+ return RequestInputUtils
+ .createMultipartHeader(MultipartType.OFPMPEXPERIMENTER, xid.getValue(), getVersion())
+ .setMultipartRequestBody(new MultipartRequestExperimenterCaseBuilder()
+ .setMultipartRequestExperimenter(new MultipartRequestExperimenterBuilder()
+ .setExperimenter(messageConverter.getExperimenterId())
+ .setExpType(messageConverter.getType())
+ .setExperimenterDataOfChoice(messageConverter
+ .convert(input.getExperimenterMessageOfChoice()))
+ .build())
+ .build())
+ .build();
+ } catch (final ConversionException e) {
+ throw new ServiceException(e);
+ }
+ }
+}
import org.opendaylight.openflowplugin.impl.services.PacketProcessingServiceImpl;
import org.opendaylight.openflowplugin.impl.services.SalEchoServiceImpl;
import org.opendaylight.openflowplugin.impl.services.SalExperimenterMessageServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.SalExperimenterMpMessageServiceImpl;
import org.opendaylight.openflowplugin.impl.services.SalFlatBatchServiceImpl;
import org.opendaylight.openflowplugin.impl.services.SalFlowServiceImpl;
import org.opendaylight.openflowplugin.impl.services.SalFlowsBatchServiceImpl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.direct.statistics.rev160511.OpendaylightDirectStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.echo.service.rev150305.SalEchoService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.SalExperimenterMessageService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SalExperimenterMpMessageService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.queue.statistics.rev131216.OpendaylightQueueStatisticsService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
-import org.opendaylight.yangtools.yang.binding.RpcService;
public class MdSalRegistrationUtils {
// register routed service instances
rpcContext.registerRpcServiceImplementation(SalEchoService.class, new SalEchoServiceImpl(rpcContext, deviceContext));
rpcContext.registerRpcServiceImplementation(SalFlowService.class, salFlowService);
- //TODO: add constructors with rcpContext and deviceContext to meter, group, table constructors
rpcContext.registerRpcServiceImplementation(FlowCapableTransactionService.class, flowCapableTransactionService);
rpcContext.registerRpcServiceImplementation(SalMeterService.class, salMeterService);
rpcContext.registerRpcServiceImplementation(SalGroupService.class, salGroupService);
rpcContext.registerRpcServiceImplementation(NodeConfigService.class, new NodeConfigServiceImpl(rpcContext, deviceContext));
rpcContext.registerRpcServiceImplementation(OpendaylightFlowStatisticsService.class, OpendaylightFlowStatisticsServiceImpl.createWithOook(rpcContext, deviceContext, convertorExecutor));
- // Direct statistics gathering
+ // register direct statistics gathering services
final OpendaylightDirectStatisticsServiceProvider statisticsProvider = new OpendaylightDirectStatisticsServiceProvider();
statisticsProvider.register(FlowDirectStatisticsService.class, new FlowDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
statisticsProvider.register(GroupDirectStatisticsService.class, new GroupDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
statisticsProvider.register(QueueDirectStatisticsService.class, new QueueDirectStatisticsService(rpcContext, deviceContext, convertorExecutor));
rpcContext.registerRpcServiceImplementation(OpendaylightDirectStatisticsService.class, new OpendaylightDirectStatisticsServiceImpl(statisticsProvider));
- final SalFlatBatchServiceImpl salFlatBatchService = new SalFlatBatchServiceImpl(
+ // register flat batch services
+ rpcContext.registerRpcServiceImplementation(SalFlatBatchService.class, new SalFlatBatchServiceImpl(
new SalFlowsBatchServiceImpl(salFlowService, flowCapableTransactionService),
new SalGroupsBatchServiceImpl(salGroupService, flowCapableTransactionService),
new SalMetersBatchServiceImpl(salMeterService, flowCapableTransactionService)
- );
- rpcContext.registerRpcServiceImplementation(SalFlatBatchService.class, salFlatBatchService);
+ ));
- // TODO: experimenter symmetric and multipart message services
+ // register experimenter services
rpcContext.registerRpcServiceImplementation(SalExperimenterMessageService.class,
new SalExperimenterMessageServiceImpl(rpcContext, deviceContext, extensionConverterProvider));
- }
-
- /**
- * Method unregisters all OF services.
- *
- * @param rpcContext - unregistration processing is implemented in {@link RpcContext}
- */
- public static void unregisterServices(@CheckForNull final RpcContext rpcContext) {
- Preconditions.checkArgument(rpcContext != null);
-
- rpcContext.unregisterRpcServiceImplementation(SalEchoService.class);
- rpcContext.unregisterRpcServiceImplementation(SalFlowService.class);
- //TODO: add constructors with rcpContext and deviceContext to meter, group, table constructors
- rpcContext.unregisterRpcServiceImplementation(FlowCapableTransactionService.class);
- rpcContext.unregisterRpcServiceImplementation(SalMeterService.class);
- rpcContext.unregisterRpcServiceImplementation(SalGroupService.class);
- rpcContext.unregisterRpcServiceImplementation(SalTableService.class);
- rpcContext.unregisterRpcServiceImplementation(SalPortService.class);
- rpcContext.unregisterRpcServiceImplementation(PacketProcessingService.class);
- rpcContext.unregisterRpcServiceImplementation(NodeConfigService.class);
- rpcContext.unregisterRpcServiceImplementation(OpendaylightFlowStatisticsService.class);
- rpcContext.unregisterRpcServiceImplementation(SalFlatBatchService.class);
- // TODO: experimenter symmetric and multipart message services
- rpcContext.unregisterRpcServiceImplementation(SalExperimenterMessageService.class);
- rpcContext.unregisterRpcServiceImplementation(OpendaylightDirectStatisticsService.class);
+ rpcContext.registerRpcServiceImplementation(SalExperimenterMpMessageService.class,
+ new SalExperimenterMpMessageServiceImpl(rpcContext, deviceContext, extensionConverterProvider));
}
/**
--- /dev/null
+/*
+ * Copyright (c) 2016 Pantheon Technologies s.r.o. 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.impl.services;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.opendaylight.openflowplugin.api.openflow.device.Xid;
+import org.opendaylight.openflowplugin.extension.api.ConvertorMessageToOFJava;
+import org.opendaylight.openflowplugin.extension.api.TypeVersionKey;
+import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.mp.message.service.rev151020.SendExperimenterMpRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenterCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.experimenter._case.MultipartRequestExperimenter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.experimenter.types.rev151020.experimenter.core.message.ExperimenterMessageOfChoice;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+public class SalExperimenterMpMessageServiceImplTest extends ServiceMocking {
+ private static final long DUMMY_ID = 42L;
+ private SalExperimenterMpMessageServiceImpl salExperimenterMpMessageService;
+
+ @Mock
+ private ExtensionConverterProvider mockedExtensionConverterProvider;
+
+ @Mock
+ private ConvertorMessageToOFJava<ExperimenterMessageOfChoice, DataContainer> mockedExtensionConverter;
+
+ @Override
+ protected void setup() {
+ when(mockedExtensionConverterProvider.getMessageConverter(Matchers.<TypeVersionKey>any()))
+ .thenReturn(mockedExtensionConverter);
+
+ when(mockedExtensionConverter.getExperimenterId())
+ .thenReturn(new ExperimenterId(DUMMY_ID));
+
+ when(mockedExtensionConverter.getType())
+ .thenReturn((long) MultipartType.OFPMPEXPERIMENTER.getIntValue());
+
+ salExperimenterMpMessageService = new SalExperimenterMpMessageServiceImpl(
+ mockedRequestContextStack,
+ mockedDeviceContext,
+ mockedExtensionConverterProvider);
+ }
+
+ @Test
+ public void sendExperimenterMpRequest() throws Exception {
+ salExperimenterMpMessageService.sendExperimenterMpRequest(new SendExperimenterMpRequestInputBuilder()
+ .setExperimenterMessageOfChoice(new DummyExperimenter())
+ .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier()))
+ .build());
+
+ verify(mockedRequestContextStack).createRequestContext();
+ }
+
+ @Test
+ public void buildRequest() throws Exception {
+ final SendExperimenterMpRequestInput data = new SendExperimenterMpRequestInputBuilder()
+ .setExperimenterMessageOfChoice(new DummyExperimenter())
+ .setNode(new NodeRef(mockedDeviceInfo.getNodeInstanceIdentifier()))
+ .build();
+
+ final OfHeader ofHeader = salExperimenterMpMessageService.buildRequest(new Xid(DUMMY_ID), data);
+ verify(mockedExtensionConverter).convert(data.getExperimenterMessageOfChoice());
+ assertEquals(DUMMY_ID, (long) ofHeader.getXid());
+ assertEquals(mockedDeviceInfo.getVersion(), (short) ofHeader.getVersion());
+ assertEquals(MultipartRequestInput.class, ofHeader.getImplementedInterface());
+
+ final MultipartRequestInput input = MultipartRequestInput.class.cast(ofHeader);
+ assertEquals(MultipartRequestExperimenterCase.class, input.getMultipartRequestBody().getImplementedInterface());
+
+ final MultipartRequestExperimenter multipartRequestExperimenter =
+ MultipartRequestExperimenterCase.class.cast(input.getMultipartRequestBody())
+ .getMultipartRequestExperimenter();
+
+ assertEquals(DUMMY_ID, (long) multipartRequestExperimenter.getExperimenter().getValue());
+ assertEquals(MultipartType.OFPMPEXPERIMENTER.getIntValue(), (long) multipartRequestExperimenter.getExpType());
+ }
+
+ private static class DummyExperimenter implements ExperimenterMessageOfChoice {
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return DummyExperimenter.class;
+ }
+ }
+}
\ No newline at end of file
public void initialization() {
when(mockedRequestContextStack.createRequestContext()).thenReturn(mockedRequestContext);
when(mockedRequestContext.getXid()).thenReturn(DUMMY_XID);
+ when(mockedRequestContext.getFuture()).thenReturn(Futures.immediateFuture(null));
when(mockedFeatures.getDatapathId()).thenReturn(DUMMY_DATAPATH_ID);
when(mockedFeatures.getVersion()).thenReturn(DUMMY_VERSION);
* Number of currently registrated services (can be changed)
* (RpcContext, DeviceContext)}
*/
- private static final int NUMBER_OF_RPC_SERVICE_REGISTRATION = 13;
+ private static final int NUMBER_OF_RPC_SERVICE_REGISTRATION = 14;
@Test
public void registerServiceTest() {