--- /dev/null
+module sal-async-config {
+ namespace "urn:opendaylight:async-config:service";
+ prefix async-config;
+
+ import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+ import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+ import opendaylight-flow-types { prefix flow-types; revision-date "2013-10-26"; }
+ import openflow-protocol { prefix ofproto; revision-date "2013-07-31"; }
+ import packet-processing { prefix packet-processing; revision-date "2013-07-09"; }
+
+ description "Asynchronous configuration message.";
+
+ revision "2017-06-19" {
+ description "Initial revision of asynchronous configuration service.";
+ }
+
+ typedef packet-in-mask {
+ type bits {
+ bit NO_MATCH;
+ bit ACTION;
+ bit INVALID_TTL;
+ }
+ }
+
+ typedef port-status-mask {
+ description "Be careful when modifying this configuration, as this can impact lldp-speaker";
+ type bits {
+ bit ADD;
+ bit DELETE;
+ bit UPDATE;
+ }
+ }
+
+ typedef flow-removed-mask {
+ description "Be careful when modifying this configuration, as this can impact FRM.";
+ type bits {
+ bit IDLE_TIMEOUT;
+ bit HARD_TIMEOUT;
+ bit DELETE;
+ bit GROUP_DELETE;
+ }
+ }
+
+ grouping async-config {
+ container packet-in-mask {
+ leaf master-mask {
+ type packet-in-mask;
+ }
+
+ leaf slave-mask {
+ type packet-in-mask;
+ }
+ }
+
+ container port-status-mask {
+ leaf master-mask {
+ type port-status-mask;
+ }
+
+ leaf slave-mask {
+ type port-status-mask;
+ }
+ }
+
+ container flow-removed-mask {
+ leaf master-mask {
+ type flow-removed-mask;
+ }
+
+ leaf slave-mask {
+ type flow-removed-mask;
+ }
+ }
+ }
+
+ container async-config-message {
+ uses ofproto:ofHeader;
+ uses async-config;
+ }
+
+ rpc set-async {
+ description "Controller to switch message set configuration.";
+
+ input {
+ uses "inv:node-context-ref";
+ uses async-config;
+ }
+ }
+
+ rpc get-async {
+ description "Controller to switch message get configuration.";
+
+ input {
+ uses "inv:node-context-ref";
+ }
+
+ output {
+ uses async-config;
+ }
+ }
+
+}
\ No newline at end of file
import org.opendaylight.openflowjava.protocol.api.keys.TypeToClassKey;
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.messages.FlowMessageDeserializer;
+import org.opendaylight.openflowplugin.impl.protocol.deserialization.messages.AsyncConfigMessageDeserializer;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.messages.GroupMessageDeserializer;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.messages.MeterMessageDeserializer;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.messages.PacketInMessageDeserializer;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.messages.PortMessageDeserializer;
import org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart.MultipartReplyMessageDeserializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupMessage;
injector.apply(10).apply(org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709
.PacketInMessage.class).accept(new PacketInMessageDeserializer());
injector.apply(19).apply(MultipartReply.class).accept(new MultipartReplyMessageDeserializer());
+ injector.apply(27).apply(AsyncConfigMessage.class).accept(new AsyncConfigMessageDeserializer());
}
/**
provider.unregisterDeserializerMapping(new TypeToClassKey(EncodeConstants.OF13_VERSION_ID, 19));
provider.registerDeserializerMapping(new TypeToClassKey(EncodeConstants.OF13_VERSION_ID, 19),
MultipartReplyMessage.class);
+ provider.unregisterDeserializerMapping(new TypeToClassKey(EncodeConstants.OF13_VERSION_ID, 27));
+ provider.registerDeserializerMapping(new TypeToClassKey(EncodeConstants.OF13_VERSION_ID, 27),
+ GetAsyncOutput.class);
}
/**
*/
@VisibleForTesting
static Function<Integer, Function<Class<? extends OfHeader>, Consumer<OFDeserializer<? extends OfHeader>>>>
- createInjector(
+ createInjector(
final DeserializerExtensionProvider provider,
final short version) {
return code -> retType -> deserializer -> {
--- /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.protocol.deserialization.messages;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.FlowRemovedMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.PacketInMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.PortStatusMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.async.config.FlowRemovedMaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.async.config.PacketInMaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.async.config.PortStatusMaskBuilder;
+
+public class AsyncConfigMessageDeserializer implements OFDeserializer<AsyncConfigMessage> {
+ @Override
+ public AsyncConfigMessage deserialize(ByteBuf message) {
+ return new AsyncConfigMessageBuilder()
+ .setVersion((short) EncodeConstants.OF13_VERSION_ID)
+ .setXid(message.readUnsignedInt())
+ .setPacketInMask(new PacketInMaskBuilder()
+ .setMasterMask(deserializePacketInMask(message))
+ .setSlaveMask(deserializePacketInMask(message))
+ .build())
+ .setPortStatusMask(new PortStatusMaskBuilder()
+ .setMasterMask(deserializePortStatusMask(message))
+ .setSlaveMask(deserializePortStatusMask(message))
+ .build())
+ .setFlowRemovedMask(new FlowRemovedMaskBuilder()
+ .setMasterMask(deserializeFlowRemovedMask(message))
+ .setSlaveMask(deserializeFlowRemovedMask(message))
+ .build())
+ .build();
+ }
+
+ private static PacketInMask deserializePacketInMask(final ByteBuf byteBuf) {
+ final long mask = byteBuf.readUnsignedInt();
+ final boolean isNoMatch = (mask & (1)) != 0;
+ final boolean isAction = (mask & (1 << 1)) != 0;
+ final boolean isInvalidTtl = (mask & (1 << 2)) != 0;
+ return new PacketInMask(isAction, isInvalidTtl, isNoMatch);
+ }
+
+ private static PortStatusMask deserializePortStatusMask(final ByteBuf byteBuf) {
+ final long mask = byteBuf.readUnsignedInt();
+ final boolean isAdd = (mask & (1)) != 0;
+ final boolean isDelete = (mask & (1 << 1)) != 0;
+ final boolean isModify = (mask & (1 << 2)) != 0;
+ return new PortStatusMask(isAdd, isDelete, isModify);
+ }
+
+ private static FlowRemovedMask deserializeFlowRemovedMask(final ByteBuf byteBuf) {
+ final long mask = byteBuf.readUnsignedInt();
+ final boolean isIdleTimeout = (mask & (1)) != 0;
+ final boolean isHardTimeout = (mask & (1 << 1)) != 0;
+ final boolean isDelete = (mask & (1 << 2)) != 0;
+ final boolean isGroupDelete = (mask & (1 << 3)) != 0;
+ return new FlowRemovedMask(isDelete, isGroupDelete, isHardTimeout, isIdleTimeout);
+ }
+}
\ No newline at end of file
import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerExtensionProvider;
import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowplugin.impl.protocol.serialization.messages.AsyncConfigMessageSerializer;
import org.opendaylight.openflowplugin.impl.protocol.serialization.messages.FlowMessageSerializer;
import org.opendaylight.openflowplugin.impl.protocol.serialization.messages.GroupMessageSerializer;
import org.opendaylight.openflowplugin.impl.protocol.serialization.messages.MeterMessageSerializer;
import org.opendaylight.openflowplugin.impl.protocol.serialization.messages.PortMessageSerializer;
import org.opendaylight.openflowplugin.impl.protocol.serialization.multipart.MultipartRequestMessageSerializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupMessage;
injector.apply(PortMessage.class).accept(new PortMessageSerializer());
injector.apply(GroupMessage.class).accept(new GroupMessageSerializer());
injector.apply(MultipartRequest.class).accept(new MultipartRequestMessageSerializer());
+ injector.apply(AsyncConfigMessage.class).accept(new AsyncConfigMessageSerializer());
}
/**
--- /dev/null
+/*
+ * Copyright (c) 2017 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.protocol.serialization.messages;
+
+import io.netty.buffer.ByteBuf;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.WeakHashMap;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.FlowRemovedMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.PacketInMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.PortStatusMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowRemovedReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
+
+public class AsyncConfigMessageSerializer extends AbstractMessageSerializer<AsyncConfigMessage> {
+ @Override
+ public void serialize(AsyncConfigMessage message, ByteBuf outBuffer) {
+ final int index = outBuffer.writerIndex();
+ super.serialize(message, outBuffer);
+
+ Optional.ofNullable(message.getPacketInMask())
+ .ifPresent(mask -> {
+ serializePacketInMask(mask.getMasterMask(), outBuffer);
+ serializePacketInMask(mask.getSlaveMask(), outBuffer);
+ });
+
+ Optional.ofNullable(message.getPortStatusMask())
+ .ifPresent(mask -> {
+ serializePortStatusMask(mask.getMasterMask(), outBuffer);
+ serializePortStatusMask(mask.getSlaveMask(), outBuffer);
+ });
+
+ Optional.ofNullable(message.getFlowRemovedMask())
+ .ifPresent(mask -> {
+ serializeFlowRemovedMask(mask.getMasterMask(), outBuffer);
+ serializeFlowRemovedMask(mask.getSlaveMask(), outBuffer);
+ });
+
+ outBuffer.setShort(index + 2, outBuffer.writerIndex() - index);
+ }
+
+ @Override
+ protected byte getMessageType() {
+ return 28;
+ }
+
+ private static void serializePacketInMask(final PacketInMask mask, final ByteBuf outBuffer) {
+ if (Objects.isNull(mask)) {
+ return;
+ }
+
+ final Map<Integer, Boolean> map = new WeakHashMap<>();
+
+ if (mask.isNOMATCH()) {
+ map.put(PacketInReason.OFPRNOMATCH.getIntValue(), true);
+ }
+
+ if (mask.isACTION()) {
+ map.put(PacketInReason.OFPRACTION.getIntValue(), true);
+ }
+
+ if (mask.isINVALIDTTL()) {
+ map.put(PacketInReason.OFPRINVALIDTTL.getIntValue(), true);
+ }
+
+ outBuffer.writeInt(ByteBufUtils.fillBitMaskFromMap(map));
+ }
+
+ private static void serializePortStatusMask(final PortStatusMask mask, final ByteBuf outBuffer) {
+ if (Objects.isNull(mask)) {
+ return;
+ }
+
+ final Map<Integer, Boolean> map = new WeakHashMap<>();
+
+ if (mask.isADD()) {
+ map.put(PortReason.OFPPRADD.getIntValue(), true);
+ }
+
+ if (mask.isDELETE()) {
+ map.put(PortReason.OFPPRDELETE.getIntValue(), true);
+ }
+
+ if (mask.isUPDATE()) {
+ map.put(PortReason.OFPPRMODIFY.getIntValue(), true);
+ }
+
+ outBuffer.writeInt(ByteBufUtils.fillBitMaskFromMap(map));
+ }
+
+ private static void serializeFlowRemovedMask(final FlowRemovedMask mask, final ByteBuf outBuffer) {
+ if (Objects.isNull(mask)) {
+ return;
+ }
+
+ final Map<Integer, Boolean> map = new WeakHashMap<>();
+
+ if (mask.isIDLETIMEOUT()) {
+ map.put(FlowRemovedReason.OFPRRIDLETIMEOUT.getIntValue(), true);
+ }
+
+ if (mask.isHARDTIMEOUT()) {
+ map.put(FlowRemovedReason.OFPRRHARDTIMEOUT.getIntValue(), true);
+ }
+
+ if (mask.isDELETE()) {
+ map.put(FlowRemovedReason.OFPRRDELETE.getIntValue(), true);
+ }
+
+ if (mask.isGROUPDELETE()) {
+ map.put(FlowRemovedReason.OFPRRGROUPDELETE.getIntValue(), true);
+ }
+
+ outBuffer.writeInt(ByteBufUtils.fillBitMaskFromMap(map));
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2017 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.sal;
+
+import com.google.common.util.concurrent.Futures;
+import java.util.Objects;
+import java.util.concurrent.Future;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerGetAsyncConfigService;
+import org.opendaylight.openflowplugin.impl.services.singlelayer.SingleLayerSetAsyncConfigService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SalAsyncConfigService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SetAsyncInput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+public class SalAsyncConfigServiceImpl implements SalAsyncConfigService {
+
+ private final SingleLayerSetAsyncConfigService setAsyncConfigService;
+ private final SingleLayerGetAsyncConfigService getAsyncConfigService;
+
+ public SalAsyncConfigServiceImpl(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+ setAsyncConfigService = new SingleLayerSetAsyncConfigService(requestContextStack, deviceContext);
+ getAsyncConfigService = new SingleLayerGetAsyncConfigService(requestContextStack, deviceContext);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> setAsync(SetAsyncInput input) {
+ return setAsyncConfigService.handleServiceCall(input);
+ }
+
+ @Override
+ public Future<RpcResult<GetAsyncOutput>> getAsync(GetAsyncInput input) {
+ return Futures.transform(getAsyncConfigService.handleServiceCall(input), result ->
+ Objects.nonNull(result) && result.isSuccessful()
+ ? RpcResultBuilder.success(new GetAsyncOutputBuilder(result.getResult())).build()
+ : RpcResultBuilder.<GetAsyncOutput>failed().build());
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2017 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.singlelayer;
+
+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.impl.services.AbstractSimpleService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class SingleLayerGetAsyncConfigService extends AbstractSimpleService<GetAsyncInput, AsyncConfigMessage> {
+
+ public SingleLayerGetAsyncConfigService(final RequestContextStack requestContextStack, final DeviceContext deviceContext) {
+ super(requestContextStack, deviceContext, AsyncConfigMessage.class);
+ }
+
+ @Override
+ protected OfHeader buildRequest(Xid xid, GetAsyncInput input) throws ServiceException {
+ return new GetAsyncInputBuilder()
+ .setVersion(getVersion())
+ .setXid(xid.getValue())
+ .build();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2017 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.singlelayer;
+
+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.impl.services.AbstractVoidService;
+import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SetAsyncInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+
+public class SingleLayerSetAsyncConfigService extends AbstractVoidService<SetAsyncInput> {
+
+ public SingleLayerSetAsyncConfigService(final RequestContextStack requestContextStack,
+ final DeviceContext deviceContext) {
+ super(requestContextStack, deviceContext);
+ }
+
+ @Override
+ protected OfHeader buildRequest(Xid xid, SetAsyncInput input) throws ServiceException {
+ return new AsyncConfigMessageBuilder(input)
+ .setVersion(getVersion())
+ .setXid(xid.getValue())
+ .build();
+ }
+}
import org.opendaylight.openflowplugin.impl.services.sal.FlowCapableTransactionServiceImpl;
import org.opendaylight.openflowplugin.impl.services.sal.NodeConfigServiceImpl;
import org.opendaylight.openflowplugin.impl.services.sal.PacketProcessingServiceImpl;
+import org.opendaylight.openflowplugin.impl.services.sal.SalAsyncConfigServiceImpl;
import org.opendaylight.openflowplugin.impl.services.sal.SalBundleServiceImpl;
import org.opendaylight.openflowplugin.impl.services.sal.SalEchoServiceImpl;
import org.opendaylight.openflowplugin.impl.services.sal.SalExperimenterMessageServiceImpl;
import org.opendaylight.openflowplugin.impl.statistics.services.direct.multilayer.MultiLayerDirectStatisticsProviderInitializer;
import org.opendaylight.openflowplugin.impl.statistics.services.direct.singlelayer.SingleLayerDirectStatisticsProviderInitializer;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SalAsyncConfigService;
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;
final SalFlowServiceImpl salFlowService = new SalFlowServiceImpl(rpcContext, deviceContext, convertorExecutor);
final FlowCapableTransactionServiceImpl flowCapableTransactionService =
new FlowCapableTransactionServiceImpl(rpcContext, deviceContext);
+ final SalAsyncConfigServiceImpl salAsyncConfigService =
+ new SalAsyncConfigServiceImpl(rpcContext, deviceContext);
final SalGroupServiceImpl salGroupService =
new SalGroupServiceImpl(rpcContext, deviceContext, convertorExecutor);
final SalMeterServiceImpl salMeterService =
new SalEchoServiceImpl(rpcContext, deviceContext));
rpcContext.registerRpcServiceImplementation(SalFlowService.class, salFlowService);
rpcContext.registerRpcServiceImplementation(FlowCapableTransactionService.class, flowCapableTransactionService);
+ rpcContext.registerRpcServiceImplementation(SalAsyncConfigService.class, salAsyncConfigService);
rpcContext.registerRpcServiceImplementation(SalMeterService.class, salMeterService);
rpcContext.registerRpcServiceImplementation(SalGroupService.class, salGroupService);
rpcContext.registerRpcServiceImplementation(SalTableService.class,
--- /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.protocol.serialization.messages;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableMap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import org.junit.Test;
+import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.openflowplugin.impl.protocol.serialization.AbstractSerializerTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.AsyncConfigMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.FlowRemovedMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.PacketInMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.PortStatusMask;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.async.config.FlowRemovedMaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.async.config.PacketInMaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.async.config.PortStatusMaskBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowRemovedReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PacketInReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortReason;
+
+public class AsyncConfigMessageSerializerTest extends AbstractSerializerTest {
+
+ private static final short LENGTH = 32;
+ private static final Long XID = 42L;
+ private static final short VERSION = EncodeConstants.OF13_VERSION_ID;
+
+ // Packet in mask
+ private static final Boolean MASTER_IS_NOMATCH = true;
+ private static final Boolean MASTER_IS_ACTION = false;
+ private static final Boolean MASTER_IS_INVALID_TTL= false;
+ private static final Boolean SLAVE_IS_NOMATCH = false;
+ private static final Boolean SLAVE_IS_ACTION = false;
+ private static final Boolean SLAVE_IS_INVALID_TTL= false;
+
+ // Port status mask
+ private static final Boolean MASTER_IS_ADD = false;
+ private static final Boolean MASTER_IS_DELETE = false;
+ private static final Boolean MASTER_IS_MODIFY = false;
+ private static final Boolean SLAVE_IS_ADD = false;
+ private static final Boolean SLAVE_IS_DELETE = false;
+ private static final Boolean SLAVE_IS_MODIFY = false;
+
+ // Flow removed mask
+ private static final Boolean MASTER_IS_IDLETIMEOUT = false;
+ private static final Boolean MASTER_IS_HARDTIMEOUT = false;
+ private static final Boolean MASTER_IS_FLOWDELETE = false;
+ private static final Boolean MASTER_IS_GROUPDELETE = false;
+ private static final Boolean SLAVE_IS_IDLETIMEOUT = false;
+ private static final Boolean SLAVE_IS_HARDTIMEOUT = false;
+ private static final Boolean SLAVE_IS_FLOWDELETE = false;
+ private static final Boolean SLAVE_IS_GROUPDELETE = false;
+
+ private static final AsyncConfigMessage MESSAGE = new AsyncConfigMessageBuilder()
+ .setXid(XID)
+ .setVersion(VERSION)
+ .setPacketInMask(new PacketInMaskBuilder()
+ .setMasterMask(new PacketInMask(MASTER_IS_ACTION, MASTER_IS_INVALID_TTL, MASTER_IS_NOMATCH))
+ .setSlaveMask(new PacketInMask(SLAVE_IS_ACTION, SLAVE_IS_INVALID_TTL, SLAVE_IS_NOMATCH))
+ .build())
+ .setPortStatusMask(new PortStatusMaskBuilder()
+ .setMasterMask(new PortStatusMask(MASTER_IS_ADD, MASTER_IS_DELETE, MASTER_IS_MODIFY))
+ .setSlaveMask(new PortStatusMask(SLAVE_IS_ADD, SLAVE_IS_DELETE, SLAVE_IS_MODIFY))
+ .build())
+ .setFlowRemovedMask(new FlowRemovedMaskBuilder()
+ .setMasterMask(new FlowRemovedMask(MASTER_IS_FLOWDELETE, MASTER_IS_GROUPDELETE,
+ MASTER_IS_HARDTIMEOUT, MASTER_IS_IDLETIMEOUT))
+ .setSlaveMask(new FlowRemovedMask(SLAVE_IS_FLOWDELETE, SLAVE_IS_GROUPDELETE,
+ SLAVE_IS_HARDTIMEOUT, SLAVE_IS_IDLETIMEOUT))
+ .build())
+ .build();
+
+ private AsyncConfigMessageSerializer serializer;
+
+ @Override
+ protected void init() {
+ serializer = getRegistry()
+ .getSerializer(new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, AsyncConfigMessage.class));
+ }
+
+ @Test
+ public void testSerialize() throws Exception {
+ final ByteBuf out = UnpooledByteBufAllocator.DEFAULT.buffer();
+ serializer.serialize(MESSAGE, out);
+
+ // Header
+ assertEquals(out.readByte(), VERSION);
+ assertEquals(out.readByte(), serializer.getMessageType());
+ assertEquals(out.readShort(), LENGTH);
+ assertEquals(out.readInt(), XID.intValue());
+
+ // Packet in master
+ assertEquals(out.readInt(), ByteBufUtils.fillBitMaskFromMap(ImmutableMap
+ .<Integer, Boolean>builder()
+ .put(PacketInReason.OFPRNOMATCH.getIntValue(), MASTER_IS_NOMATCH)
+ .put(PacketInReason.OFPRACTION.getIntValue(), MASTER_IS_ACTION)
+ .put(PacketInReason.OFPRINVALIDTTL.getIntValue(), MASTER_IS_INVALID_TTL)
+ .build()));
+
+ // Packet in slave
+ assertEquals(out.readInt(), ByteBufUtils.fillBitMaskFromMap(ImmutableMap
+ .<Integer, Boolean>builder()
+ .put(PacketInReason.OFPRNOMATCH.getIntValue(), SLAVE_IS_NOMATCH)
+ .put(PacketInReason.OFPRACTION.getIntValue(), SLAVE_IS_ACTION)
+ .put(PacketInReason.OFPRINVALIDTTL.getIntValue(), SLAVE_IS_INVALID_TTL)
+ .build()));
+
+ // Port status master
+ assertEquals(out.readInt(), ByteBufUtils.fillBitMaskFromMap(ImmutableMap
+ .<Integer, Boolean>builder()
+ .put(PortReason.OFPPRADD.getIntValue(), MASTER_IS_ADD)
+ .put(PortReason.OFPPRDELETE.getIntValue(), MASTER_IS_DELETE)
+ .put(PortReason.OFPPRMODIFY.getIntValue(), MASTER_IS_MODIFY)
+ .build()));
+
+ // Port status slave
+ assertEquals(out.readInt(), ByteBufUtils.fillBitMaskFromMap(ImmutableMap
+ .<Integer, Boolean>builder()
+ .put(PortReason.OFPPRADD.getIntValue(), SLAVE_IS_ADD)
+ .put(PortReason.OFPPRDELETE.getIntValue(), SLAVE_IS_DELETE)
+ .put(PortReason.OFPPRMODIFY.getIntValue(), SLAVE_IS_MODIFY)
+ .build()));
+
+ // Flow removed master
+ assertEquals(out.readInt(), ByteBufUtils.fillBitMaskFromMap(ImmutableMap
+ .<Integer, Boolean>builder()
+ .put(FlowRemovedReason.OFPRRIDLETIMEOUT.getIntValue(), MASTER_IS_IDLETIMEOUT)
+ .put(FlowRemovedReason.OFPRRHARDTIMEOUT.getIntValue(), MASTER_IS_HARDTIMEOUT)
+ .put(FlowRemovedReason.OFPRRDELETE.getIntValue(), MASTER_IS_FLOWDELETE)
+ .put(FlowRemovedReason.OFPRRGROUPDELETE.getIntValue(), MASTER_IS_GROUPDELETE)
+ .build()));
+
+ // Flow removed slave
+ assertEquals(out.readInt(), ByteBufUtils.fillBitMaskFromMap(ImmutableMap
+ .<Integer, Boolean>builder()
+ .put(FlowRemovedReason.OFPRRIDLETIMEOUT.getIntValue(), SLAVE_IS_IDLETIMEOUT)
+ .put(FlowRemovedReason.OFPRRHARDTIMEOUT.getIntValue(), SLAVE_IS_HARDTIMEOUT)
+ .put(FlowRemovedReason.OFPRRDELETE.getIntValue(), SLAVE_IS_FLOWDELETE)
+ .put(FlowRemovedReason.OFPRRGROUPDELETE.getIntValue(), SLAVE_IS_GROUPDELETE)
+ .build()));
+
+ assertEquals(out.readableBytes(), 0);
+ }
+
+}
\ No newline at end of file
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
/**
- * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.FlowCapableTransactionServiceImpl}.
+ * Test for {@link FlowCapableTransactionServiceImpl}.
*/
public class FlowCapableTransactionServiceImplTest extends ServiceMocking {
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
/**
- * Test for {@link org.opendaylight.openflowplugin.impl.services.sal.PacketProcessingServiceImpl}.
+ * Test for {@link PacketProcessingServiceImpl}.
*/
public class PacketProcessingServiceImplTest extends ServiceMocking {
--- /dev/null
+/*
+ * Copyright (c) 2017 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.sal;
+
+import static org.mockito.Mockito.verify;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+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.Matchers;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.openflowplugin.impl.services.ServiceMocking;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.GetAsyncOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.async.config.service.rev170619.SetAsyncInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetAsyncInput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+/**
+ * Test for {@link SalAsyncConfigServiceImpl}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class SalAsyncConfigServiceImplTest extends ServiceMocking {
+
+ private SalAsyncConfigServiceImpl salAsyncConfigService;
+
+ @Before
+ public void setUp() throws Exception {
+ salAsyncConfigService = new SalAsyncConfigServiceImpl(
+ mockedRequestContextStack, mockedDeviceContext);
+ }
+
+ @Test
+ public void testSetAsync() throws Exception {
+ final SetAsyncInput setAsyncInput = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol
+ .rev130731.SetAsyncInputBuilder().build();
+ final RpcResult<SetAsyncInput> replyRpcResult = RpcResultBuilder.success(setAsyncInput).build();
+ final ListenableFuture<RpcResult<SetAsyncInput>> replyFuture = Futures.immediateFuture(replyRpcResult);
+ Mockito.when(mockedRequestContext.getFuture()).thenReturn(replyFuture);
+
+ final Future<RpcResult<Void>> setAsyncResult =
+ salAsyncConfigService.setAsync(new SetAsyncInputBuilder().build());
+
+ Assert.assertNotNull(setAsyncResult);
+ Assert.assertTrue(setAsyncResult.isDone());
+ Assert.assertTrue(setAsyncResult.get().isSuccessful());
+ verify(mockedRequestContextStack).createRequestContext();
+ }
+
+ @Test
+ public void testGetAsyncTest() throws Exception {
+ final GetAsyncOutput getAsyncOutput = new GetAsyncOutputBuilder().build();
+ final RpcResult<GetAsyncOutput> replyRpcResult = RpcResultBuilder.success(getAsyncOutput).build();
+ final ListenableFuture<RpcResult<GetAsyncOutput>> replyFuture = Futures.immediateFuture(replyRpcResult);
+ Mockito.when(mockedRequestContext.getFuture()).thenReturn(replyFuture);
+
+ final Future<RpcResult<GetAsyncOutput>> getAsyncResult =
+ salAsyncConfigService.getAsync(new GetAsyncInputBuilder().build());
+
+ Assert.assertNotNull(getAsyncResult);
+ Assert.assertTrue(getAsyncResult.isDone());
+ Assert.assertTrue(getAsyncResult.get().isSuccessful());
+ verify(mockedRequestContextStack).createRequestContext();
+ verify(mockedOutboundQueue).commitEntry(Matchers.eq(ServiceMocking.DUMMY_XID_VALUE),
+ Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
+ }
+}
\ No newline at end of file
* Number of currently registrated services (can be changed)
* (RpcContext, DeviceContext)}.
*/
- private static final int NUMBER_OF_RPC_SERVICE_REGISTRATION = 15;
+ private static final int NUMBER_OF_RPC_SERVICE_REGISTRATION = 16;
private static final int NUMBER_OF_STAT_COMPAT_RPC_SERVICE_REGISTRATION = 5;
@Mock
.registerConvertor(OFConstants.OFP_VERSION_1_0, flowFlagsV10Convertor)
.registerConvertor(OFConstants.OFP_VERSION_1_3, flowFlagsConvertor);
}
-}
\ No newline at end of file
+}