BUG-4826: BGP Evpn Nlri's handlers 94/37594/5
authorClaudio D. Gasparini <cgaspari@cisco.com>
Tue, 5 Apr 2016 09:24:28 +0000 (11:24 +0200)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Tue, 19 Apr 2016 18:20:43 +0000 (20:20 +0200)
Evpn Nlri cases handlers
https://tools.ietf.org/html/rfc7432#section-7

Change-Id: I385e20a0e510328761c1f341a8c7744182dc5850
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/BGPActivator.java [moved from bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/BGPActivator.java with 81% similarity]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/AbstractEvpnNlri.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EthADRParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EthSegRParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EvpnNlriParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/IncMultEthTagRParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/MACIpAdvRParser.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/NlriActivator.java [new file with mode: 0644]
bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/NlriModelUtil.java [new file with mode: 0644]

similarity index 81%
rename from bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/BGPActivator.java
rename to bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/BGPActivator.java
index 6ec8eaefc5f7ae1eed5a7e4e81f8eec01373ce31..8ebe42514551df0ec0f60bf95b8d17c5c07bda0f 100644 (file)
@@ -5,7 +5,8 @@
  * 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;
+
+package org.opendaylight.protocol.bgp.evpn.impl;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -14,19 +15,28 @@ import org.opendaylight.protocol.bgp.evpn.impl.extended.communities.DefaultGatew
 import org.opendaylight.protocol.bgp.evpn.impl.extended.communities.ESILabelExtCom;
 import org.opendaylight.protocol.bgp.evpn.impl.extended.communities.ESImpRouteTargetExtCom;
 import org.opendaylight.protocol.bgp.evpn.impl.extended.communities.MACMobExtCom;
+import org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriActivator;
 import org.opendaylight.protocol.bgp.parser.spi.AbstractBGPExtensionProviderActivator;
 import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.EvpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.L2vpnAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.routes.evpn.routes.evpn.route.attributes.extended.communities.extended.community.DefaultGatewayExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.extended.communities.extended.community.EsImportRouteExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.extended.communities.extended.community.EsiLabelExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.extended.communities.extended.community.MacMobilityExtendedCommunityCase;
 
+public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
+    private static final int L2VPN_AFI = 25;
+    private static final int EVPN_SAFI = 70;
 
-public class BGPActivator extends AbstractBGPExtensionProviderActivator {
     @Override
     protected List<AutoCloseable> startImpl(final BGPExtensionProviderContext context) {
         final List<AutoCloseable> regs = new ArrayList<>();
 
+        regs.add(context.registerSubsequentAddressFamily(EvpnSubsequentAddressFamily.class, EVPN_SAFI));
+        regs.add(context.registerAddressFamily(L2vpnAddressFamily.class, L2VPN_AFI));
+
+        NlriActivator.registerNlriParsers(regs);
         registerExtendedCommunities(context, regs);
         ESIActivator.registerEsiTypeParsers(regs);
         return regs;
@@ -49,4 +59,6 @@ public class BGPActivator extends AbstractBGPExtensionProviderActivator {
         regs.add(context.registerExtendedCommunityParser(macEC.getType(true), macEC.getSubType(), macEC));
         regs.add(context.registerExtendedCommunitySerializer(MacMobilityExtendedCommunityCase.class, macEC));
     }
-}
\ No newline at end of file
+
+
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/AbstractEvpnNlri.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/AbstractEvpnNlri.java
new file mode 100644 (file)
index 0000000..4d58c78
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.nlri;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.evpn.spi.EvpnParser;
+import org.opendaylight.protocol.bgp.evpn.spi.EvpnSerializer;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEsiTypeRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
+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.EvpnChoice;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+
+abstract class AbstractEvpnNlri implements EvpnParser, EvpnSerializer {
+
+    static final int MAC_ADDRESS_LENGTH = 6;
+    static final int ESI_SIZE = 10;
+    private static final NodeIdentifier ESI_NID = NodeIdentifier.create(Esi.QNAME);
+    static final int ZERO_BYTE = 1;
+
+    @Override
+    public final ByteBuf serializeEvpn(final EvpnChoice evpn, final ByteBuf common) {
+        final ByteBuf output = Unpooled.buffer();
+        final ByteBuf body = serializeBody(evpn);
+        output.writeByte(getType().getIntValue());
+        output.writeByte(body.readableBytes() + common.readableBytes());
+        output.writeBytes(common);
+        output.writeBytes(body);
+        return output;
+    }
+
+    protected abstract NlriType getType();
+
+    protected abstract ByteBuf serializeBody(final EvpnChoice evpn);
+
+    protected static Esi serializeEsi(final ContainerNode evpn) {
+        return SimpleEsiTypeRegistry.getInstance().parseEsiModel((ChoiceNode) evpn.getChild(ESI_NID).get());
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EthADRParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EthADRParser.java
new file mode 100644 (file)
index 0000000..9df01a0
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.nlri;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.MPLS_NID;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractETI;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractMplsLabel;
+import static org.opendaylight.protocol.util.MplsLabelUtil.byteBufForMplsLabel;
+import static org.opendaylight.protocol.util.MplsLabelUtil.mplsLabelForByteBuf;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEsiTypeRegistry;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
+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.ethernet.a.d.route.EthernetADRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.a.d.route.EthernetADRouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.EvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.EthernetADRouteCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.EthernetADRouteCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+
+final class EthADRParser extends AbstractEvpnNlri {
+    protected static final NodeIdentifier ETH_AD_ROUTE_NID = new NodeIdentifier(EthernetADRoute.QNAME);
+    private static final int CONTENT_LENGTH = 17;
+
+    @Override
+    public EvpnChoice parseEvpn(final ByteBuf buffer) {
+        Preconditions.checkArgument(buffer.readableBytes() == CONTENT_LENGTH, "Wrong length of array of bytes. Passed: %s ;", buffer);
+        final Esi esi = SimpleEsiTypeRegistry.getInstance().parseEsi(buffer.readSlice(ESI_SIZE));
+        final EthernetTagId eti = new EthernetTagIdBuilder().setVlanId(buffer.readUnsignedInt()).build();
+        final MplsLabel label = mplsLabelForByteBuf(buffer);
+        final EthernetADRouteBuilder builder = new EthernetADRouteBuilder().setEsi(esi).setEthernetTagId(eti).setMplsLabel(label);
+        return new EthernetADRouteCaseBuilder().setEthernetADRoute(builder.build()).build();
+    }
+
+    @Override
+    protected NlriType getType() {
+        return NlriType.EthADDisc;
+    }
+
+    @Override
+    public ByteBuf serializeBody(final EvpnChoice evpn) {
+        Preconditions.checkArgument(evpn instanceof EthernetADRouteCase, "Unknown evpn instance. Passed %s. Needed EthernetADRouteCase.", evpn.getClass());
+        return serializeBody(((EthernetADRouteCase) evpn).getEthernetADRoute());
+    }
+
+    @Override
+    public EvpnChoice serializeEvpnModel(final ContainerNode evpn) {
+        final EthernetADRouteBuilder builder = serializeKeyModel(evpn);
+        builder.setMplsLabel(extractMplsLabel(evpn, MPLS_NID));
+        return new EthernetADRouteCaseBuilder().setEthernetADRoute(builder.build()).build();
+    }
+
+    @Override
+    public EvpnChoice createRouteKey(final ContainerNode evpn) {
+        return new EthernetADRouteCaseBuilder().setEthernetADRoute(serializeKeyModel(evpn).build()).build();
+    }
+
+    private static EthernetADRouteBuilder serializeKeyModel(final ContainerNode evpn) {
+        final EthernetADRouteBuilder builder = new EthernetADRouteBuilder();
+        builder.setEsi(serializeEsi(evpn));
+        builder.setEthernetTagId(extractETI(evpn));
+        return builder;
+    }
+
+    private static ByteBuf serializeBody(final EthernetADRoute evpn) {
+        final ByteBuf body = Unpooled.buffer(CONTENT_LENGTH);
+        SimpleEsiTypeRegistry.getInstance().serializeEsi(evpn.getEsi(), body);
+        ByteBufWriteUtil.writeUnsignedInt(evpn.getEthernetTagId().getVlanId(), body);
+
+        final MplsLabel mpls = evpn.getMplsLabel();
+        if (mpls != null) {
+            body.writeBytes(byteBufForMplsLabel(evpn.getMplsLabel()));
+        }
+        return body;
+    }
+}
\ No newline at end of file
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EthSegRParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EthSegRParser.java
new file mode 100644 (file)
index 0000000..0ffe868
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.nlri;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractOrigRouteIp;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEsiTypeRegistry;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.es.route.EsRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.es.route.EsRouteBuilder;
+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.EvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.EsRouteCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.EsRouteCaseBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+
+final class EthSegRParser extends AbstractEvpnNlri {
+    protected static final NodeIdentifier ES_ROUTE_NID = new NodeIdentifier(EsRoute.QNAME);
+    private static final int CONTENT_LENGTH = 15;
+    private static final int CONTENT_LENGTH2 = 27;
+
+    @Override
+    public EvpnChoice parseEvpn(final ByteBuf buffer) {
+        Preconditions.checkArgument(buffer.readableBytes() == CONTENT_LENGTH || buffer.readableBytes() == CONTENT_LENGTH2,
+            "Wrong length of array of bytes. Passed: %s ;", buffer);
+
+        final Esi esi = SimpleEsiTypeRegistry.getInstance().parseEsi(buffer.readSlice(ESI_SIZE));
+        final IpAddress ip = Preconditions.checkNotNull(parseOrigRouteIp(buffer));
+
+        final EsRouteBuilder builder = new EsRouteBuilder().setEsi(esi).setOrigRouteIp(ip);
+        return new EsRouteCaseBuilder().setEsRoute(builder.build()).build();
+    }
+
+    @Override
+    protected NlriType getType() {
+        return NlriType.EthSeg;
+    }
+
+    @Override
+    public ByteBuf serializeBody(final EvpnChoice evpnInput) {
+        Preconditions.checkArgument(evpnInput instanceof EsRouteCase, "Unknown evpn instance. Passed %s. Needed EsRouteCase.",
+            evpnInput.getClass());
+        return serializeBody(((EsRouteCase) evpnInput).getEsRoute());
+    }
+
+    @Override
+    public EvpnChoice serializeEvpnModel(final ContainerNode evpnCase) {
+        return createRouteKey(evpnCase);
+    }
+
+    @Override
+    public EvpnChoice createRouteKey(final ContainerNode evpn) {
+        final EsRouteBuilder builder = new EsRouteBuilder();
+        builder.setEsi(serializeEsi(evpn));
+        builder.setOrigRouteIp(extractOrigRouteIp(evpn));
+        return new EsRouteCaseBuilder().setEsRoute(builder.build()).build();
+    }
+
+    private static ByteBuf serializeBody(final EsRoute evpn) {
+        final ByteBuf body = Unpooled.buffer();
+        SimpleEsiTypeRegistry.getInstance().serializeEsi(evpn.getEsi(), body);
+        final ByteBuf orig = serializeOrigRouteIp(evpn.getOrigRouteIp());
+        Preconditions.checkArgument(orig.readableBytes() > 0);
+        body.writeBytes(orig);
+        return body;
+    }
+
+    public static IpAddress parseOrigRouteIp(final ByteBuf buffer) {
+        final int ipLength = buffer.readByte();
+        if (ipLength == Ipv6Util.IPV6_LENGTH) {
+            return new IpAddress(Ipv6Util.addressForByteBuf(buffer));
+        } else if (ipLength == Ipv4Util.IP4_LENGTH) {
+            return new IpAddress(Ipv4Util.addressForByteBuf(buffer));
+        }
+        return null;
+    }
+
+    static ByteBuf serializeOrigRouteIp(final IpAddress origRouteIp) {
+        final ByteBuf body = Unpooled.buffer();
+        if (origRouteIp.getIpv4Address() != null) {
+            body.writeByte(Ipv4Util.IP4_LENGTH);
+            body.writeBytes(Ipv4Util.bytesForAddress(origRouteIp.getIpv4Address()));
+        } else if (origRouteIp.getIpv6Address() != null) {
+            body.writeByte(Ipv6Util.IPV6_LENGTH);
+            body.writeBytes(Ipv6Util.bytesForAddress(origRouteIp.getIpv6Address()));
+        } else {
+            body.writeZero(ZERO_BYTE);
+        }
+        return body;
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EvpnNlriParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/EvpnNlriParser.java
new file mode 100644 (file)
index 0000000..5dc0d0c
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * 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.nlri;
+
+import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.parseRouteDistinguisher;
+import static org.opendaylight.bgp.concepts.RouteDistinguisherUtil.serializeRouteDistinquisher;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractRouteDistinguisher;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.opendaylight.protocol.bgp.evpn.spi.EvpnRegistry;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEvpnNlriRegistry;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
+import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.EvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.destination.EvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.destination.EvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationEvpnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.evpn._case.DestinationEvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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.DataContainerNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class EvpnNlriParser implements NlriParser, NlriSerializer {
+    private static final Logger LOG = LoggerFactory.getLogger(EvpnNlriParser.class);
+    private static final NodeIdentifier EVPN_CHOICE_NID = new NodeIdentifier(EvpnChoice.QNAME);
+
+    public static EvpnDestination extractEvpnDestination(final DataContainerNode<? extends PathArgument> evpnChoice) {
+        final EvpnRegistry reg = SimpleEvpnNlriRegistry.getInstance();
+        final ChoiceNode choiceCont = (ChoiceNode) evpnChoice.getChild(EVPN_CHOICE_NID).get();
+        final EvpnChoice evpnValue = reg.serializeEvpnModel(choiceCont);
+        if (evpnValue == null) {
+            LOG.warn("Unrecognized Nlri {}", choiceCont);
+            return null;
+        }
+        return new EvpnDestinationBuilder().setRouteDistinguisher(extractRouteDistinguisher(evpnChoice)).setEvpnChoice(evpnValue).build();
+    }
+
+    public static EvpnDestination extractRouteKeyDestination(final DataContainerNode<? extends PathArgument> evpnChoice) {
+        final EvpnRegistry reg = SimpleEvpnNlriRegistry.getInstance();
+        final ChoiceNode choiceCont = (ChoiceNode) evpnChoice.getChild(EVPN_CHOICE_NID).get();
+        final EvpnChoice evpnValue = reg.serializeEvpnRouteKey(choiceCont);
+        if (evpnValue == null) {
+            LOG.warn("Unrecognized Nlri {}", choiceCont);
+            return null;
+        }
+        return new EvpnDestinationBuilder().setRouteDistinguisher(extractRouteDistinguisher(evpnChoice)).setEvpnChoice(evpnValue).build();
+    }
+
+    @Override
+    public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
+        if (!nlri.isReadable()) {
+            return;
+        }
+        final List<EvpnDestination> dst = parseNlri(nlri);
+
+        builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.
+                routes.destination.type.DestinationEvpnCaseBuilder().setDestinationEvpn(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.
+                yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.evpn._case.DestinationEvpnBuilder()
+                .setEvpnDestination(dst).build()).build()).build());
+    }
+
+    @Override
+    public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
+        if (!nlri.isReadable()) {
+            return;
+        }
+        final List<EvpnDestination> dst = parseNlri(nlri);
+
+        builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
+            new DestinationEvpnCaseBuilder().setDestinationEvpn(new DestinationEvpnBuilder().setEvpnDestination(dst).build()).build()).build());
+    }
+
+    @Nullable
+    private List<EvpnDestination> parseNlri(final ByteBuf nlri) {
+        if (!nlri.isReadable()) {
+            return null;
+        }
+        final List<EvpnDestination> dests = new ArrayList<>();
+
+        while (nlri.isReadable()) {
+            final EvpnDestinationBuilder builder = new EvpnDestinationBuilder();
+            final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
+            final int length = nlri.readUnsignedByte();
+            final ByteBuf nlriBuf = nlri.readSlice(length);
+            builder.setRouteDistinguisher(parseRouteDistinguisher(nlriBuf));
+            builder.setEvpnChoice(SimpleEvpnNlriRegistry.getInstance().parseEvpn(type, nlriBuf));
+            dests.add(builder.build());
+        }
+        return dests;
+    }
+
+    @Override
+    public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
+        Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a Attributes object");
+        final Attributes pathAttributes = (Attributes) attribute;
+        final Attributes1 pathAttributes1 = pathAttributes.getAugmentation(Attributes1.class);
+        final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
+        if (pathAttributes1 != null) {
+            final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
+            if ((routes != null) && (routes.getDestinationType() instanceof DestinationEvpnCase)) {
+                final DestinationEvpnCase evpnCase = (DestinationEvpnCase) routes.getDestinationType();
+                serializeNlri(evpnCase.getDestinationEvpn().getEvpnDestination(), byteAggregator);
+            }
+        } else if (pathAttributes2 != null) {
+            final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
+            final WithdrawnRoutes withdrawnRoutes = mpUnreachNlri.getWithdrawnRoutes();
+            if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml
+                .ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase) {
+                final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.
+                    routes.destination.type.DestinationEvpnCase evpnCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml
+                    .ns.yang.bgp.evpn.rev160321.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationEvpnCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
+                serializeNlri(evpnCase.getDestinationEvpn().getEvpnDestination(), byteAggregator);
+            }
+        }
+    }
+
+    public static void serializeNlri(final List<EvpnDestination> cEvpn, final ByteBuf output) {
+        ByteBuf nlriOutput = null;
+        for (final EvpnDestination dest : cEvpn) {
+            final ByteBuf nlriCommon = Unpooled.buffer();
+            serializeRouteDistinquisher(dest.getRouteDistinguisher(), nlriCommon);
+            nlriOutput = SimpleEvpnNlriRegistry.getInstance().serializeEvpn(dest.getEvpnChoice(), nlriCommon);
+        }
+        output.writeBytes(nlriOutput);
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/IncMultEthTagRParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/IncMultEthTagRParser.java
new file mode 100644 (file)
index 0000000..a08b753
--- /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.impl.nlri;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractETI;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractOrigRouteIp;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.EvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.IncMultiEthernetTagResCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.IncMultiEthernetTagResCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.inc.multi.ethernet.tag.res.IncMultiEthernetTagRes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.inc.multi.ethernet.tag.res.IncMultiEthernetTagResBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+
+final class IncMultEthTagRParser extends AbstractEvpnNlri {
+    protected static final NodeIdentifier INC_MULT_ROUTE_NID = new NodeIdentifier(IncMultiEthernetTagRes.QNAME);
+    private static final int CONTENT_LENGTH = 9;
+    private static final int CONTENT_LENGTH2 = 21;
+
+    @Override
+    public EvpnChoice parseEvpn(final ByteBuf buffer) {
+        Preconditions.checkArgument(buffer.readableBytes() == CONTENT_LENGTH || buffer.readableBytes() == CONTENT_LENGTH2,
+            "Wrong length of array of bytes. Passed: %s ;", buffer);
+
+        final EthernetTagId eti = new EthernetTagIdBuilder().setVlanId(buffer.readUnsignedInt()).build();
+        IpAddress ip = Preconditions.checkNotNull(EthSegRParser.parseOrigRouteIp(buffer));
+        final IncMultiEthernetTagResBuilder builder = new IncMultiEthernetTagResBuilder().setEthernetTagId(eti).setOrigRouteIp(ip);
+        return new IncMultiEthernetTagResCaseBuilder().setIncMultiEthernetTagRes(builder.build()).build();
+    }
+
+    @Override
+    protected NlriType getType() {
+        return NlriType.IncMultEthTag;
+    }
+
+    @Override
+    public ByteBuf serializeBody(final EvpnChoice evpn) {
+        Preconditions.checkArgument(evpn instanceof IncMultiEthernetTagResCase, "Unknown evpn instance. Passed %s. Needed IncMultiEthernetTagResCase.",
+            evpn.getClass());
+        return serializeBody(((IncMultiEthernetTagResCase) evpn).getIncMultiEthernetTagRes());
+    }
+
+    @Override
+    public EvpnChoice serializeEvpnModel(final ContainerNode evpn) {
+        return createRouteKey(evpn);
+    }
+
+    @Override
+    public EvpnChoice createRouteKey(final ContainerNode evpn) {
+        final IncMultiEthernetTagResBuilder builder = new IncMultiEthernetTagResBuilder();
+        builder.setEthernetTagId(extractETI(evpn));
+        builder.setOrigRouteIp(extractOrigRouteIp(evpn));
+        return new IncMultiEthernetTagResCaseBuilder().setIncMultiEthernetTagRes(builder.build()).build();
+    }
+
+    private static ByteBuf serializeBody(final IncMultiEthernetTagRes evpn) {
+        final ByteBuf body = Unpooled.buffer();
+        ByteBufWriteUtil.writeUnsignedInt(evpn.getEthernetTagId().getVlanId(), body);
+        final ByteBuf orig = EthSegRParser.serializeOrigRouteIp(evpn.getOrigRouteIp());
+        Preconditions.checkArgument(orig.readableBytes() > 0);
+        body.writeBytes(orig);
+        return body;
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/MACIpAdvRParser.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/MACIpAdvRParser.java
new file mode 100644 (file)
index 0000000..062405f
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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.nlri;
+
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.MPLS1_NID;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.MPLS2_NID;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractETI;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractIp;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractMAC;
+import static org.opendaylight.protocol.bgp.evpn.impl.nlri.NlriModelUtil.extractMplsLabel;
+import static org.opendaylight.protocol.util.MplsLabelUtil.byteBufForMplsLabel;
+import static org.opendaylight.protocol.util.MplsLabelUtil.mplsLabelForByteBuf;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEsiTypeRegistry;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.protocol.util.ByteBufWriteUtil;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.protocol.util.Ipv6Util;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.IetfYangUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.NlriType;
+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.ethernet.tag.id.EthernetTagId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.EvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.MacIpAdvRouteCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.MacIpAdvRouteCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.mac.ip.adv.route.MacIpAdvRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.mac.ip.adv.route.MacIpAdvRouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+
+final class MACIpAdvRParser extends AbstractEvpnNlri {
+    static final NodeIdentifier MAC_IP_ADV_ROUTE_NID = new NodeIdentifier(MacIpAdvRoute.QNAME);
+    private static final int BITS_SIZE = 8;
+
+    @Override
+    public EvpnChoice parseEvpn(final ByteBuf buffer) {
+        final Esi esi = SimpleEsiTypeRegistry.getInstance().parseEsi(buffer.readSlice(ESI_SIZE));
+        final EthernetTagId eti = new EthernetTagIdBuilder().setVlanId(buffer.readUnsignedInt()).build();
+        buffer.skipBytes(1);
+        final MacAddress mac = IetfYangUtil.INSTANCE.macAddressFor(ByteArray.readBytes(buffer, MAC_ADDRESS_LENGTH));
+        final IpAddress ip = parseIp(buffer);
+        final MplsLabel label1 = mplsLabelForByteBuf(buffer);
+        MplsLabel label2;
+        if (buffer.readableBytes() > 0) {
+            label2 = mplsLabelForByteBuf(buffer);
+        } else {
+            label2 = null;
+        }
+        final MacIpAdvRouteBuilder builder = new MacIpAdvRouteBuilder().setEsi(esi).setEthernetTagId(eti).setMacAddress(mac).setIpAddress(ip)
+            .setMplsLabel1(label1).setMplsLabel2(label2);
+        return new MacIpAdvRouteCaseBuilder().setMacIpAdvRoute(builder.build()).build();
+    }
+
+    @Override
+    protected NlriType getType() {
+        return NlriType.MacIpAdv;
+    }
+
+    @Override
+    public ByteBuf serializeBody(final EvpnChoice evpn) {
+        Preconditions.checkArgument(evpn instanceof MacIpAdvRouteCase, "Unknown evpn instance. Passed %s. Needed MacIpAdvRouteCase.", evpn.getClass());
+        return serializeBody((MacIpAdvRouteCase) evpn);
+    }
+
+    @Override
+    public EvpnChoice serializeEvpnModel(final ContainerNode evpn) {
+        final MacIpAdvRouteBuilder builder = serializeKeyModel(evpn);
+        builder.setEsi(serializeEsi(evpn));
+        builder.setMplsLabel1(extractMplsLabel(evpn, MPLS1_NID));
+        builder.setMplsLabel2(extractMplsLabel(evpn, MPLS2_NID));
+        return new MacIpAdvRouteCaseBuilder().setMacIpAdvRoute(builder.build()).build();
+    }
+
+    @Override
+    public EvpnChoice createRouteKey(final ContainerNode evpn) {
+        return new MacIpAdvRouteCaseBuilder().setMacIpAdvRoute(serializeKeyModel(evpn).build()).build();
+    }
+
+    private static MacIpAdvRouteBuilder serializeKeyModel(final ContainerNode evpn) {
+        final MacIpAdvRouteBuilder builder = new MacIpAdvRouteBuilder();
+        builder.setEthernetTagId(extractETI(evpn));
+        builder.setMacAddress(extractMAC(evpn));
+        builder.setIpAddress(extractIp(evpn));
+        return builder;
+    }
+
+    private static ByteBuf serializeBody(final MacIpAdvRouteCase evpnCase) {
+        final ByteBuf body = Unpooled.buffer();
+        final MacIpAdvRoute evpn = evpnCase.getMacIpAdvRoute();
+        final Esi esi = evpn.getEsi();
+        if (esi != null) {
+            SimpleEsiTypeRegistry.getInstance().serializeEsi(evpn.getEsi(), body);
+        }
+        ByteBufWriteUtil.writeUnsignedInt(evpn.getEthernetTagId().getVlanId(), body);
+
+        final MacAddress mac = evpn.getMacAddress();
+        body.writeByte(MAC_ADDRESS_LENGTH * BITS_SIZE);
+        body.writeBytes(IetfYangUtil.INSTANCE.bytesFor(mac));
+        final ByteBuf ipAddress = serializeIp(evpn.getIpAddress());
+        Preconditions.checkArgument(ipAddress.readableBytes() > 0);
+        body.writeBytes(ipAddress);
+        final MplsLabel mpls1 = evpn.getMplsLabel1();
+        if (mpls1 != null) {
+            body.writeBytes(byteBufForMplsLabel(mpls1));
+        }
+        final MplsLabel mpls2 = evpn.getMplsLabel2();
+        if (mpls2 != null) {
+            body.writeBytes(byteBufForMplsLabel(mpls2));
+        }
+        return body;
+    }
+
+    private static ByteBuf serializeIp(final IpAddress ipAddress) {
+        final ByteBuf body = Unpooled.buffer();
+        if (ipAddress.getIpv4Address() != null) {
+            body.writeByte(Ipv4Util.IP4_LENGTH * BITS_SIZE);
+            body.writeBytes(Ipv4Util.bytesForAddress(ipAddress.getIpv4Address()));
+        } else if (ipAddress.getIpv6Address() != null) {
+            body.writeByte(Ipv6Util.IPV6_LENGTH * BITS_SIZE);
+            body.writeBytes(Ipv6Util.bytesForAddress(ipAddress.getIpv6Address()));
+        } else {
+            body.writeZero(ZERO_BYTE);
+        }
+        return body;
+    }
+
+    private static IpAddress parseIp(final ByteBuf buffer) {
+        final int ipLength = buffer.readUnsignedByte();
+        if (ipLength == Ipv6Util.IPV6_LENGTH * BITS_SIZE) {
+            return new IpAddress(Ipv6Util.addressForByteBuf(buffer));
+        } else if (ipLength == Ipv4Util.IP4_LENGTH * BITS_SIZE) {
+            return new IpAddress(Ipv4Util.addressForByteBuf(buffer));
+        }
+        return null;
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/NlriActivator.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/NlriActivator.java
new file mode 100644 (file)
index 0000000..b242033
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.nlri;
+
+import java.util.List;
+import org.opendaylight.protocol.bgp.evpn.spi.pojo.SimpleEvpnNlriRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.es.route.EsRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.a.d.route.EthernetADRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.EsRouteCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.EthernetADRouteCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.IncMultiEthernetTagResCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.evpn.choice.MacIpAdvRouteCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.inc.multi.ethernet.tag.res.IncMultiEthernetTagRes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.mac.ip.adv.route.MacIpAdvRoute;
+
+public final class NlriActivator {
+    private NlriActivator() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static void registerNlriParsers(final List<AutoCloseable> regs) {
+        final SimpleEvpnNlriRegistry evpnNlriRegistry = SimpleEvpnNlriRegistry.getInstance();
+
+        final EthADRParser ethADR = new EthADRParser();
+        regs.add(evpnNlriRegistry.registerNlriParser(ethADR.getType(), ethADR));
+        regs.add(evpnNlriRegistry.registerNlriSerializer(EthernetADRouteCase.class, ethADR));
+        regs.add(evpnNlriRegistry.registerNlriModelSerializer(EthernetADRoute.QNAME, ethADR));
+
+        final MACIpAdvRParser macIpAR = new MACIpAdvRParser();
+        regs.add(evpnNlriRegistry.registerNlriParser(macIpAR.getType(), macIpAR));
+        regs.add(evpnNlriRegistry.registerNlriSerializer(MacIpAdvRouteCase.class, macIpAR));
+        regs.add(evpnNlriRegistry.registerNlriModelSerializer(MacIpAdvRoute.QNAME, macIpAR));
+
+        final IncMultEthTagRParser incMultETR = new IncMultEthTagRParser();
+        regs.add(evpnNlriRegistry.registerNlriParser(incMultETR.getType(), incMultETR));
+        regs.add(evpnNlriRegistry.registerNlriSerializer(IncMultiEthernetTagResCase.class, incMultETR));
+        regs.add(evpnNlriRegistry.registerNlriModelSerializer(IncMultiEthernetTagRes.QNAME, incMultETR));
+
+        final EthSegRParser ethSR = new EthSegRParser();
+        regs.add(evpnNlriRegistry.registerNlriParser(ethSR.getType(), ethSR));
+        regs.add(evpnNlriRegistry.registerNlriSerializer(EsRouteCase.class, ethSR));
+        regs.add(evpnNlriRegistry.registerNlriModelSerializer(EsRoute.QNAME, ethSR));
+    }
+}
diff --git a/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/NlriModelUtil.java b/bgp/evpn/src/main/java/org/opendaylight/protocol/bgp/evpn/impl/nlri/NlriModelUtil.java
new file mode 100644 (file)
index 0000000..3129951
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.nlri;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.ethernet.tag.id.EthernetTagIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.evpn.rev160321.evpn.EvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+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.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+
+final class NlriModelUtil {
+    static final NodeIdentifier ETI_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "ethernet-tag-id").intern());
+    static final NodeIdentifier VLAN_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "vlan-id").intern());
+    static final NodeIdentifier RD_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "route-distinguisher").intern());
+    static final NodeIdentifier ORI_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "orig-route-ip").intern());
+    static final NodeIdentifier MAC_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "mac-address").intern());
+    static final NodeIdentifier IP_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "ip-address").intern());
+    static final NodeIdentifier MPLS_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "mpls-label").intern());
+    static final NodeIdentifier MPLS1_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "mpls-label1").intern());
+    static final NodeIdentifier MPLS2_NID = NodeIdentifier.create(QName.create(EvpnChoice.QNAME, "mpls-label2").intern());
+
+    private NlriModelUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    static RouteDistinguisher extractRouteDistinguisher(final DataContainerNode<? extends PathArgument> evpn) {
+        return RouteDistinguisherBuilder.getDefaultInstance((String) evpn.getChild(RD_NID).get().getValue());
+    }
+
+    static IpAddress extractOrigRouteIp(final DataContainerNode<? extends PathArgument> evpn) {
+        return IpAddressBuilder.getDefaultInstance((String) evpn.getChild(ORI_NID).get().getValue());
+    }
+
+
+    static EthernetTagId extractETI(final ContainerNode evpn) {
+        final ContainerNode eti = (ContainerNode) evpn.getChild(ETI_NID).get();
+        return new EthernetTagIdBuilder().setVlanId((Long) eti.getChild(VLAN_NID).get().getValue()).build();
+    }
+
+    static MacAddress extractMAC(final DataContainerNode<? extends PathArgument> evpn) {
+        return new MacAddress((String) evpn.getChild(MAC_NID).get().getValue());
+    }
+
+
+    static IpAddress extractIp(final DataContainerNode<? extends PathArgument> evpn) {
+        if (evpn.getChild(IP_NID).isPresent()) {
+            return IpAddressBuilder.getDefaultInstance((String) evpn.getChild(IP_NID).get().getValue());
+        }
+        return null;
+    }
+
+    static MplsLabel extractMplsLabel(final DataContainerNode<? extends PathArgument> evpn, final NodeIdentifier mplsNid) {
+        if (evpn.getChild(mplsNid).isPresent()) {
+            return new MplsLabel((Long) evpn.getChild(mplsNid).get().getValue());
+        }
+        return null;
+    }
+}