From f623757172feeb9de24cfcca2b40f2d6344019ed Mon Sep 17 00:00:00 2001 From: Tomas Slusny Date: Tue, 29 Nov 2016 10:33:51 +0100 Subject: [PATCH] Add InstructionSerializerInjector Add injector where all instruction serializers will be registered and call it from general SerializerInjector Add AbstractInstructionSerializer and AbstractActionInstructionSerializer to unify all instruction serializers Add unit tests Change-Id: Id2c2462c950b127636f040b452226b2216e097ec Signed-off-by: Tomas Slusny --- .../InstructionSerializerInjector.java | 49 ++++++++++++++++ .../serialization/SerializerInjector.java | 1 + .../AbstractActionInstructionSerializer.java | 56 +++++++++++++++++++ .../AbstractInstructionSerializer.java | 41 ++++++++++++++ .../InstructionSerializerInjectorTest.java | 51 +++++++++++++++++ .../AbstractInstructionSerializerTest.java | 54 ++++++++++++++++++ 6 files changed, 252 insertions(+) create mode 100644 openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjector.java create mode 100644 openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractActionInstructionSerializer.java create mode 100644 openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializer.java create mode 100644 openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjectorTest.java create mode 100644 openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializerTest.java diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjector.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjector.java new file mode 100644 index 0000000000..a75d200da5 --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjector.java @@ -0,0 +1,49 @@ +/* + * 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; + +import com.google.common.annotations.VisibleForTesting; +import java.util.function.Consumer; +import java.util.function.Function; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +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.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction; + +/** + * Util class for injecting new instruction serializers into OpenflowJava + */ +class InstructionSerializerInjector { + + /** + * Injects serializers into provided {@link org.opendaylight.openflowjava.protocol.api.extensibility.SerializerExtensionProvider} + * @param provider OpenflowJava serializer extension provider + */ + static void injectSerializers(final SerializerExtensionProvider provider) { + // Inject new instruction serializers here using injector created by createInjector method + final Function, Consumer>> injector = + createInjector(provider, EncodeConstants.OF13_VERSION_ID); + } + + /** + * Create injector that will inject new serializers into #{@link org.opendaylight.openflowjava.protocol.api.extensibility.SerializerExtensionProvider} + * @param provider OpenflowJava serializer extension provider + * @param version Openflow version + * @return injector + */ + @VisibleForTesting + static Function, Consumer>> createInjector(final SerializerExtensionProvider provider, + final byte version) { + return type -> serializer -> + provider.registerSerializer( + new MessageTypeKey<>(version, type), + serializer); + } +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/SerializerInjector.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/SerializerInjector.java index 4b84dbfc8f..4af3d12211 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/SerializerInjector.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/SerializerInjector.java @@ -23,6 +23,7 @@ public class SerializerInjector { // Inject new serializers here MatchSerializerInjector.injectSerializers(provider); ActionSerializerInjector.injectSerializers(provider); + InstructionSerializerInjector.injectSerializers(provider); MessageSerializerInjector.injectSerializers(provider); } } diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractActionInstructionSerializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractActionInstructionSerializer.java new file mode 100644 index 0000000000..47904b72e3 --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractActionInstructionSerializer.java @@ -0,0 +1,56 @@ +/* + * 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.instructions; + +import io.netty.buffer.ByteBuf; +import java.util.Optional; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry; +import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants; +import org.opendaylight.openflowplugin.impl.protocol.serialization.util.ActionUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.ActionList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction; + +public abstract class AbstractActionInstructionSerializer extends AbstractInstructionSerializer implements SerializerRegistryInjector { + + private SerializerRegistry registry; + + @Override + public void serialize(Instruction input, ByteBuf outBuffer) { + outBuffer.writeShort(getType()); + } + + /** + * Try to write list of OpenFlowPlugin actions to output buffer + * @param actions List of OpenFlowPlugin actions + * @param outBuffer output buffer + * @param startIndex start index of byte buffer + */ + protected void writeActions(ActionList actions, short version, ByteBuf outBuffer, int startIndex) { + Optional.ofNullable(actions).flatMap(as -> Optional.ofNullable(as.getAction())).map(as -> { + int lengthIndex = outBuffer.writerIndex(); + outBuffer.writeShort(EncodeConstants.EMPTY_LENGTH); + outBuffer.writeZero(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION); + ActionUtil.sortActions(as).forEach(a -> ActionUtil.writeAction(a.getAction(), version, registry, outBuffer)); + outBuffer.setShort(lengthIndex, outBuffer.writerIndex() - startIndex); + return actions; + }).orElseGet(() -> { + outBuffer.writeShort(getLength()); + outBuffer.writeZero(InstructionConstants.PADDING_IN_ACTIONS_INSTRUCTION); + return actions; + }); + } + + @Override + public void injectSerializerRegistry(SerializerRegistry serializerRegistry) { + registry = serializerRegistry; + } + +} diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializer.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializer.java new file mode 100644 index 0000000000..2eb20f9b9c --- /dev/null +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializer.java @@ -0,0 +1,41 @@ +/* + * 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.instructions; + +import io.netty.buffer.ByteBuf; +import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction; + +public abstract class AbstractInstructionSerializer implements OFSerializer, HeaderSerializer { + + @Override + public void serialize(Instruction input, ByteBuf outBuffer) { + outBuffer.writeShort(getType()); + outBuffer.writeShort(getLength()); + } + + @Override + public void serializeHeader(Instruction input, ByteBuf outBuffer) { + outBuffer.writeShort(getType()); + outBuffer.writeShort(InstructionConstants.INSTRUCTION_IDS_LENGTH); + } + + /** + * @return numeric representation of instruction type + */ + protected abstract int getType(); + + /** + * @return instruction length + */ + protected abstract int getLength(); + +} diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjectorTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjectorTest.java new file mode 100644 index 0000000000..daa899539b --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/InstructionSerializerInjectorTest.java @@ -0,0 +1,51 @@ +/* + * 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; + +import static org.mockito.Mockito.verify; + +import java.util.function.Consumer; +import java.util.function.Function; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer; +import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase; + +@RunWith(MockitoJUnitRunner.class) +public class InstructionSerializerInjectorTest { + + @Mock + private SwitchConnectionProvider switchConnectionProvider; + + @Mock + private OFSerializer instructionSerializer; + + private Function, Consumer>> injector; + + @Before + public void setUp() throws Exception { + injector = InstructionSerializerInjector.createInjector(switchConnectionProvider, EncodeConstants.OF13_VERSION_ID); + } + + @Test + public void injectSerializers() throws Exception { + injector.apply(ApplyActionsCase.class).accept(instructionSerializer); + verify(switchConnectionProvider).registerSerializer( + new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, ApplyActionsCase.class), + instructionSerializer); + } + +} \ No newline at end of file diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializerTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializerTest.java new file mode 100644 index 0000000000..9e05b6865d --- /dev/null +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/protocol/serialization/instructions/AbstractInstructionSerializerTest.java @@ -0,0 +1,54 @@ +/* + * 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.instructions; + +import static org.junit.Assert.assertEquals; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.UnpooledByteBufAllocator; +import java.util.function.Consumer; +import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey; +import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants; +import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants; +import org.opendaylight.openflowplugin.impl.protocol.serialization.AbstractSerializerTest; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction; + +public abstract class AbstractInstructionSerializerTest extends AbstractSerializerTest { + private AbstractInstructionSerializer serializer; + + @Override + protected void init() { + serializer = getRegistry().getSerializer(new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, getClazz())); + } + + protected void assertInstruction(final Instruction instruction, final Consumer assertBody) { + // Header serialization + final ByteBuf bufferHeader = UnpooledByteBufAllocator.DEFAULT.buffer(); + serializer.serializeHeader(instruction, bufferHeader); + assertEquals(bufferHeader.readUnsignedShort(), getType()); + assertEquals(bufferHeader.readUnsignedShort(), InstructionConstants.INSTRUCTION_IDS_LENGTH); + assertEquals(bufferHeader.readableBytes(), 0); + + // Header and body serialization + final ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer(); + serializer.serialize(instruction, buffer); + assertEquals(buffer.readUnsignedShort(), getType()); + assertEquals(buffer.readUnsignedShort(), getLength()); + assertBody.accept(buffer); + assertEquals(buffer.readableBytes(), 0); + } + + protected AbstractInstructionSerializer getSerializer() { + return serializer; + } + + protected abstract Class getClazz(); + protected abstract int getType(); + protected abstract int getLength(); +} \ No newline at end of file -- 2.36.6