--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+}
throw new UnsupportedOperationException();
}
- static final Long extractLD(final ContainerNode cont) {
+ static Long extractLD(final ContainerNode cont) {
return (Long) cont.getChild(LD_NID).get().getValue();
}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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