BUG-4826: Evpn ESI Registry 90/37590/3
authorClaudio D. Gasparini <cgaspari@cisco.com>
Tue, 5 Apr 2016 09:57:10 +0000 (11:57 +0200)
committerMilos Fabian <milfabia@cisco.com>
Mon, 18 Apr 2016 07:57:00 +0000 (07:57 +0000)
Evpn ESI Registry Implementation

Change-Id: I50ee6ddf717fe1553c7b57197ee91e43ad91f349
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/BGPActivator.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/esi/types/ESIActivator.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/esi/types/EsiModelUtil.java
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/spi/EsiRegistry.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/spi/pojo/SimpleEsiTypeRegistry.java [new file with mode: 0644]
bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/spi/pojo/SimpleEsiTypeRegistryTest.java [new file with mode: 0644]

diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/BGPActivator.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/BGPActivator.java
new file mode 100644 (file)
index 0000000..3346f47
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.evpn;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.bgp.evpn.impl.esi.types.ESIActivator;
+import org.opendaylight.protocol.bgp.parser.spi.AbstractBGPExtensionProviderActivator;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+
+public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
+    @Override
+    protected List<AutoCloseable> startImpl(final BGPExtensionProviderContext context) {
+        final List<AutoCloseable> regs = new ArrayList<>();
+
+        ESIActivator.registerEsiTypeParsers(regs);
+        return regs;
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/esi/types/ESIActivator.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/esi/types/ESIActivator.java
new file mode 100644 (file)
index 0000000..0575216
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.evpn.impl.esi.types;
+
+import java.util.List;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEsiTypeRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.ArbitraryCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.AsGeneratedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.LacpAutoGeneratedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.LanAutoGeneratedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.MacAutoGeneratedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.RouterIdGeneratedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.arbitrary._case.Arbitrary;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.as.generated._case.AsGenerated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.lacp.auto.generated._case.LacpAutoGenerated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.lan.auto.generated._case.LanAutoGenerated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.mac.auto.generated._case.MacAutoGenerated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.esi.router.id.generated._case.RouterIdGenerated;
+
+public final class ESIActivator {
+    private ESIActivator() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static void registerEsiTypeParsers(final List<AutoCloseable> regs) {
+        final SimpleEsiTypeRegistry esiRegistry = SimpleEsiTypeRegistry.getInstance();
+
+        final ArbitraryParser t0Parser = new ArbitraryParser();
+        regs.add(esiRegistry.registerEsiParser(t0Parser.getType(), t0Parser));
+        regs.add(esiRegistry.registerEsiSerializer(ArbitraryCase.class, t0Parser));
+        regs.add(esiRegistry.registerEsiModelSerializer(Arbitrary.QNAME, t0Parser));
+
+        final LacpParser t1Parser = new LacpParser();
+        regs.add(esiRegistry.registerEsiParser(t1Parser.getType(), t1Parser));
+        regs.add(esiRegistry.registerEsiSerializer(LacpAutoGeneratedCase.class, t1Parser));
+        regs.add(esiRegistry.registerEsiModelSerializer(LacpAutoGenerated.QNAME, t1Parser));
+
+        final LanParser t2Parser = new LanParser();
+        regs.add(esiRegistry.registerEsiParser(t2Parser.getType(), t2Parser));
+        regs.add(esiRegistry.registerEsiSerializer(LanAutoGeneratedCase.class, t2Parser));
+        regs.add(esiRegistry.registerEsiModelSerializer(LanAutoGenerated.QNAME, t2Parser));
+
+        final MacParser t3Parser = new MacParser();
+        regs.add(esiRegistry.registerEsiParser(t3Parser.getType(), t3Parser));
+        regs.add(esiRegistry.registerEsiSerializer(MacAutoGeneratedCase.class, t3Parser));
+        regs.add(esiRegistry.registerEsiModelSerializer(MacAutoGenerated.QNAME, t3Parser));
+
+        final RouterIdParser t4Parser = new RouterIdParser();
+        regs.add(esiRegistry.registerEsiParser(t4Parser.getType(), t4Parser));
+        regs.add(esiRegistry.registerEsiSerializer(RouterIdGeneratedCase.class, t4Parser));
+        regs.add(esiRegistry.registerEsiModelSerializer(RouterIdGenerated.QNAME, t4Parser));
+
+        final ASGenParser t5Parser = new ASGenParser();
+        regs.add(esiRegistry.registerEsiParser(t5Parser.getType(), t5Parser));
+        regs.add(esiRegistry.registerEsiSerializer(AsGeneratedCase.class, t5Parser));
+        regs.add(esiRegistry.registerEsiModelSerializer(AsGenerated.QNAME, t5Parser));
+    }
+}
index d4f8e9d635c078458c0408ebda0427f8227686b7..a961c2ea720180578bef013fb27caf692b687432 100644 (file)
@@ -33,7 +33,7 @@ final class EsiModelUtil {
         throw new UnsupportedOperationException();
     }
 
-    static final Long extractLD(final ContainerNode cont) {
+    static Long extractLD(final ContainerNode cont) {
         return (Long) cont.getChild(LD_NID).get().getValue();
     }
 
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/spi/EsiRegistry.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/spi/EsiRegistry.java
new file mode 100644 (file)
index 0000000..31dd629
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.evpn.spi;
+
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.Esi;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+
+public interface EsiRegistry {
+    /**
+     * Parse Esi
+     *
+     * @param buffer encoded ESI body in Bytebuf
+     * @return Ethernet Segment Identifier
+     */
+    Esi parseEsi(ByteBuf buffer);
+
+    /**
+     * Parse Esi Model
+     *
+     * @param esi ChoiceNode containing ESI
+     * @return Ethernet Segment Identifier
+     */
+    Esi parseEsiModel(ChoiceNode esi);
+
+    /**
+     * Serialize Esi
+     *
+     * @param esi Ethernet Segment Identifier
+     * @param buffer write in Bytebuf encoded ESI body
+     */
+    void serializeEsi(Esi esi, ByteBuf buffer);
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/spi/pojo/SimpleEsiTypeRegistry.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/spi/pojo/SimpleEsiTypeRegistry.java
new file mode 100644 (file)
index 0000000..0af770f
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.evpn.spi.pojo;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.evpn.spi.EsiParser;
+import org.opendaylight.protocol.bgp.evpn.spi.EsiRegistry;
+import org.opendaylight.protocol.bgp.evpn.spi.EsiSerializer;
+import org.opendaylight.protocol.concepts.HandlerRegistry;
+import org.opendaylight.protocol.concepts.MultiRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.EsiType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.Esi;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class SimpleEsiTypeRegistry implements EsiRegistry {
+    private static final Logger LOG = LoggerFactory.getLogger(SimpleEsiTypeRegistry.class);
+    private static final SimpleEsiTypeRegistry SINGLETON = new SimpleEsiTypeRegistry();
+    private static final int CONTENT_LENGTH = 10;
+    private static final int ESI_LENGTH = 9;
+    private final HandlerRegistry<DataContainer, EsiParser, EsiSerializer> handlers = new HandlerRegistry<>();
+    private final MultiRegistry<NodeIdentifier, EsiSerializer> modelHandlers = new MultiRegistry<>();
+
+    private SimpleEsiTypeRegistry() {
+    }
+
+    public static SimpleEsiTypeRegistry getInstance() {
+        return SINGLETON;
+    }
+
+    public AutoCloseable registerEsiParser(final EsiType esiType, final EsiParser parser) {
+        return this.handlers.registerParser(esiType.getIntValue(), parser);
+    }
+
+    public AutoCloseable registerEsiSerializer(final Class<? extends Esi> esiType, final EsiSerializer serializer) {
+        return this.handlers.registerSerializer(esiType, serializer);
+    }
+
+    public AutoCloseable registerEsiModelSerializer(final QName qName, final EsiSerializer serializer) {
+        return this.modelHandlers.register(new NodeIdentifier(qName), serializer);
+    }
+
+    @Override
+    public Esi parseEsi(final ByteBuf buffer) {
+        Preconditions.checkArgument(buffer != null && buffer.isReadable(), "Array of bytes is mandatory. Can't be null or empty.");
+        Preconditions.checkArgument(buffer.readableBytes() == CONTENT_LENGTH, "Wrong length of array of bytes. Passed: " + buffer.readableBytes() + ";");
+
+        final EsiParser parser = this.handlers.getParser(EsiType.forValue(buffer.readByte()).getIntValue());
+        if (parser == null) {
+            return null;
+        }
+        return parser.parseEsi(buffer.readSlice(ESI_LENGTH));
+    }
+
+    @Override
+    public Esi parseEsiModel(final ChoiceNode esiChoice) {
+        Preconditions.checkArgument(esiChoice != null && !esiChoice.getValue().isEmpty(), "ESI is mandatory. Can't be null or empty.");
+        for (final DataContainerChild<? extends PathArgument, ?> entry : esiChoice.getValue()) {
+            final EsiSerializer serializer = this.modelHandlers.get((NodeIdentifier) entry.getIdentifier());
+            if (serializer != null) {
+                return serializer.serializeEsi((ContainerNode) entry);
+            }
+        }
+        LOG.warn("Unrecognized ESI {}", esiChoice);
+        return null;
+    }
+
+    @Override
+    public void serializeEsi(final Esi esi, final ByteBuf buffer) {
+        final EsiSerializer serializer = this.handlers.getSerializer(esi.getImplementedInterface());
+        if (serializer == null) {
+            return;
+        }
+        serializer.serializeEsi(esi, buffer);
+    }
+}
diff --git a/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/spi/pojo/SimpleEsiTypeRegistryTest.java b/bgp/evpn/src/test/java/org/opendaylight/protocol/bgp/evpn/spi/pojo/SimpleEsiTypeRegistryTest.java
new file mode 100644 (file)
index 0000000..7109430
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.evpn.spi.pojo;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.opendaylight.protocol.bgp.evpn.impl.esi.types.RouterIdParserTest.ROUTE_ID_CASE;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.evpn.impl.esi.types.ESIActivator;
+import org.opendaylight.protocol.bgp.evpn.impl.esi.types.RouterIdParserTest;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.esi.Esi;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.routes.evpn.routes.EvpnRoute;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+
+public class SimpleEsiTypeRegistryTest {
+    private static final int ESI_TYPE_LENGTH = 10;
+
+    private class notRegistered implements Esi {
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return notRegistered.class;
+        }
+    }
+
+    @Before
+    public void setUp() {
+        ESIActivator.registerEsiTypeParsers(new ArrayList<>());
+    }
+
+    @Test
+    public void registryTest() {
+        final ByteBuf buff = Unpooled.buffer(ESI_TYPE_LENGTH);
+        SimpleEsiTypeRegistry.getInstance().serializeEsi(ROUTE_ID_CASE, buff);
+        assertArrayEquals(RouterIdParserTest.RESULT, ByteArray.getAllBytes(buff));
+        assertEquals(ROUTE_ID_CASE, SimpleEsiTypeRegistry.getInstance().parseEsiModel(RouterIdParserTest.createRouterIdCase()));
+        assertEquals(RouterIdParserTest.ROUTE_ID_CASE, SimpleEsiTypeRegistry.getInstance().parseEsi(Unpooled.wrappedBuffer(buff)));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void registryParseTest() {
+        SimpleEsiTypeRegistry.getInstance().parseEsi(null);
+    }
+
+    @Test
+    public void registryNullTest() {
+        final ByteBuf body = Unpooled.buffer();
+        SimpleEsiTypeRegistry.getInstance().serializeEsi(new notRegistered(), body);
+        assertEquals(0, body.readableBytes());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void registryNullModelTest() {
+        final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ChoiceNode> noRegister = Builders.choiceBuilder();
+        noRegister.withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(EvpnRoute.QNAME, "no-register").intern()));
+        assertNull(SimpleEsiTypeRegistry.getInstance().parseEsiModel(noRegister.build()));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void registryEmptyModelTest() {
+        assertNull(SimpleEsiTypeRegistry.getInstance().parseEsiModel(null));
+    }
+}
\ No newline at end of file