MVPN Support 14/72114/1
authorClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Tue, 15 May 2018 11:36:45 +0000 (13:36 +0200)
committerClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Mon, 21 May 2018 12:28:10 +0000 (14:28 +0200)
- Nlri Handlers
- RIB Supports
- Add supported family to default RIB/Peer config
- BGP/RIB Activator
- Increment test coverage

JIRA: BGPCEP-396
Change-Id: Ib020247ab87aa7baa303703c552cfecf1c7314d9
Signed-off-by: Claudio D. Gasparini <claudio.gasparini@pantheon.tech>
26 files changed:
bgp/config-example/src/main/resources/initial/protocols-config.xml
bgp/mvpn/pom.xml
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/AbstractMvpnRIBSupport.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/BGPActivator.java
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv4RIBSupport.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv6RIBSupport.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/RIBActivator.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/CMulticastUtil.java
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/Ipv4NlriHandler.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/Ipv6NlriHandler.java [new file with mode: 0644]
bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/MvpnNlriHandler.java [new file with mode: 0644]
bgp/mvpn/src/main/resources/META-INF/services/org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderActivator [new file with mode: 0644]
bgp/mvpn/src/main/resources/org/opendaylight/blueprint/bgp-mvpn.xml
bgp/mvpn/src/main/yang/bgp-mvpn-ipv4.yang
bgp/mvpn/src/main/yang/bgp-mvpn-ipv6.yang
bgp/mvpn/src/main/yang/bgp-mvpn.yang
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/BGPActivatorTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv4RIBSupportTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv6RIBSupportTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/RIBActivatorTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/TableTypeActivatorTest.java [new file with mode: 0644]
bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/spi/pojo/nlri/SimpleMvpnNlriRegistryTest.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/AbstractRIBSupport.java
bgp/rib-spi/src/test/java/org/opendaylight/protocol/bgp/rib/spi/AbstractRIBSupportTest.java
features/bgp/odl-bgpcep-bgp/pom.xml
features/bmp/odl-bgpcep-bmp/pom.xml

index 24729868e6197b8d0c743088bfa50d4243ffbbdd..86639d4d64ebd30279446e614b7168304974b4c4 100644 (file)
                     <afi-safi>
                         <afi-safi-name>IPV6-L3VPN-FLOW</afi-safi-name>
                     </afi-safi>
+                    <afi-safi>
+                        <afi-safi-name>IPV4-MCAST-VPN</afi-safi-name>
+                    </afi-safi>
+                    <afi-safi>
+                        <afi-safi-name>IPV6-MCAST-VPN</afi-safi-name>
+                    </afi-safi>
                 </afi-safis>
             </global>
             <neighbors>
                         <afi-safi>
                             <afi-safi-name>IPV6-L3VPN-FLOW</afi-safi-name>
                         </afi-safi>
+                        <afi-safi>
+                            <afi-safi-name>IPV4-MCAST-VPN</afi-safi-name>
+                        </afi-safi>
+                        <afi-safi>
+                            <afi-safi-name>IPV6-MCAST-VPN</afi-safi-name>
+                        </afi-safi>
                     </afi-safis>
                 </peer-group>
                 <peer-group>
                         <afi-safi>
                             <afi-safi-name>IPV6-L3VPN-FLOW</afi-safi-name>
                         </afi-safi>
+                        <afi-safi>
+                            <afi-safi-name>IPV4-MCAST-VPN</afi-safi-name>
+                        </afi-safi>
+                        <afi-safi>
+                            <afi-safi-name>IPV6-MCAST-VPN</afi-safi-name>
+                        </afi-safi>
                     </afi-safis>
                 </peer-group>
             </peer-groups>
index 8af1e54ba153338e09e3c2dcac70a6919ab8f0ea..73483ff28882b5991b55c95b25179aff6768e456 100644 (file)
     <name>${project.artifactId}</name>
 
     <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-parser-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>bgp-parser-spi</artifactId>
             <groupId>org.opendaylight.mdsal.model</groupId>
             <artifactId>ietf-inet-types-2013-07-15</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal.model</groupId>
+            <artifactId>yang-ext</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>yang-binding</artifactId>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>bgp-parser-api</artifactId>
+            <artifactId>bgp-rib-api</artifactId>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>bgp-rib-spi</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-openconfig-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-openconfig-spi</artifactId>
+        </dependency>
         <!-- test scope dependencies -->
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-rib-spi</artifactId>
+            <type>test-jar</type>
             <scope>test</scope>
         </dependency>
         <dependency>
             <artifactId>bgp-parser-impl</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>mockito-configuration</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-dom-adapter</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
     </dependencies>
 
     <scm>
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/AbstractMvpnRIBSupport.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/AbstractMvpnRIBSupport.java
new file mode 100644 (file)
index 0000000..1954fc1
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import java.util.Optional;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupport;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.PathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.McastVpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.MvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRouteKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+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.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract Mvpn RIBSupport.
+ *
+ * @author Claudio D. Gasparini
+ */
+public abstract class AbstractMvpnRIBSupport<C extends Routes & DataObject>
+        extends AbstractRIBSupport<C, MvpnRoutes, MvpnRoute, MvpnRouteKey> {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMvpnRIBSupport.class);
+    private final NodeIdentifier nlriRoutesList;
+
+    /**
+     * Default constructor. Requires the QName of the container augmented under the routes choice
+     * node in instantiations of the rib grouping. It is assumed that this container is defined by
+     * the same model which populates it with route grouping instantiation, and by extension with
+     * the route attributes container.
+     *
+     * @param mappingService     Serialization service
+     * @param cazeClass          Binding class of the AFI/SAFI-specific case statement, must not be null
+     * @param afiClass           address Family Class
+     * @param destContainerQname destination container Qname
+     * @param destListQname      destinations list Qname
+     */
+    AbstractMvpnRIBSupport(
+            final BindingNormalizedNodeSerializer mappingService,
+            final Class<C> cazeClass,
+            final Class<? extends AddressFamily> afiClass,
+            final QName destContainerQname,
+            final QName destListQname) {
+        super(mappingService, cazeClass, MvpnRoutes.class, MvpnRoute.class, afiClass,
+                McastVpnSubsequentAddressFamily.class, destContainerQname);
+        this.nlriRoutesList = NodeIdentifier.create(destListQname);
+    }
+
+    @Override
+    public final MvpnRoute createRoute(final MvpnRoute route, final String routeKey, final long pathId,
+            final Attributes attributes) {
+        final MvpnRouteBuilder builder;
+        if (route != null) {
+            builder = new MvpnRouteBuilder(route);
+        } else {
+            builder = new MvpnRouteBuilder();
+        }
+        return builder.setKey(createRouteListKey(pathId, routeKey)).setAttributes(attributes).build();
+    }
+
+    @Override
+    public final MvpnRouteKey createRouteListKey(final long pathId, final String routeKey) {
+        return new MvpnRouteKey(new PathId(pathId), routeKey);
+    }
+
+    final MvpnChoice extractMvpnChoice(final DataContainerNode<? extends PathArgument> route) {
+        final DataObject nn = this.mappingService.fromNormalizedNode(this.routeDefaultYii, route).getValue();
+        return ((MvpnRoute) nn).getMvpnChoice();
+    }
+
+    @Override
+    protected final void processDestination(
+            DOMDataWriteTransaction tx,
+            final YangInstanceIdentifier routesPath,
+            final ContainerNode destination,
+            final ContainerNode attributes,
+            final ApplyRoute function) {
+        if (destination != null) {
+            final Optional<DataContainerChild<? extends PathArgument, ?>> maybeRoutes = destination
+                    .getChild(nlriRoutesList);
+            if (maybeRoutes.isPresent()) {
+                final DataContainerChild<? extends PathArgument, ?> routes = maybeRoutes.get();
+                if (routes instanceof UnkeyedListNode) {
+                    final YangInstanceIdentifier base = routesPath.node(routesContainerIdentifier()).node(routeNid());
+                    for (final UnkeyedListEntryNode mvpnDest : ((UnkeyedListNode) routes).getValue()) {
+                        final YangInstanceIdentifier.NodeIdentifierWithPredicates routeKey = createRouteKey(mvpnDest);
+                        function.apply(tx, base, routeKey, mvpnDest, attributes);
+                    }
+                } else {
+                    LOG.warn("Routes {} are not a map", routes);
+                }
+            }
+        }
+    }
+
+    abstract NodeIdentifierWithPredicates createRouteKey(UnkeyedListEntryNode mvpn);
+}
index ab8247673c1b78c046ed8b81d15665a63a637358..9e05f76054c7a971d2c8c8d22ab6730307a26899 100644 (file)
@@ -11,16 +11,24 @@ package org.opendaylight.protocol.bgp.mvpn.impl;
 import com.google.common.annotations.VisibleForTesting;
 import java.util.ArrayList;
 import java.util.List;
+import org.opendaylight.protocol.bgp.inet.codec.nexthop.Ipv4NextHopParserSerializer;
+import org.opendaylight.protocol.bgp.inet.codec.nexthop.Ipv6NextHopParserSerializer;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.PEDistinguisherLabelsAttributeHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.PMSITunnelAttributeHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.extended.community.SourceAS4OctectHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.extended.community.SourceASHandler;
 import org.opendaylight.protocol.bgp.mvpn.impl.attributes.extended.community.VrfRouteImportHandler;
+import org.opendaylight.protocol.bgp.mvpn.impl.nlri.MvpnNlriHandler;
 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.mvpn.rev180417.McastVpnSubsequentAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.bgp.rib.route.attributes.extended.communities.extended.community.SourceAs4ExtendedCommunityCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.bgp.rib.route.attributes.extended.communities.extended.community.SourceAsExtendedCommunityCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.c.next.hop.Ipv4NextHopCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.c.next.hop.Ipv6NextHopCase;
 
 /**
  * Registers NLRI, Attributes, Extended communities Handlers.
@@ -29,7 +37,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn
  */
 public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
     @VisibleForTesting
-    private static final int MVPN_SAFI = 5;
+    static final int MVPN_SAFI = 5;
 
     private static void registerAttributesHandler(
             final BGPExtensionProviderContext context,
@@ -44,10 +52,18 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
         regs.add(context.registerAttributeSerializer(pmsiParser.getClazz(), pmsiParser));
     }
 
-    private static void registerNlriHandler(
+    private static void registerNlri(
             final BGPExtensionProviderContext context,
             final List<AutoCloseable> regs) {
-        //TODO
+        final MvpnNlriHandler mvpnNlriHandler = new MvpnNlriHandler();
+        final Ipv4NextHopParserSerializer ipv4NextHopParser = new Ipv4NextHopParserSerializer();
+        final Ipv6NextHopParserSerializer ipv6NextHopParser = new Ipv6NextHopParserSerializer();
+        regs.add(context.registerNlriParser(Ipv4AddressFamily.class, McastVpnSubsequentAddressFamily.class,
+                mvpnNlriHandler, ipv4NextHopParser, Ipv4NextHopCase.class));
+        regs.add(context.registerNlriParser(Ipv6AddressFamily.class, McastVpnSubsequentAddressFamily.class,
+                mvpnNlriHandler, ipv6NextHopParser, Ipv6NextHopCase.class));
+        regs.add(context.registerNlriSerializer(MvpnRoutes.class, mvpnNlriHandler));
+
     }
 
     private static void registerExtendedCommunities(final BGPExtensionProviderContext context,
@@ -79,9 +95,10 @@ public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
         final List<AutoCloseable> regs = new ArrayList<>();
         TunnelIdentifierActivator.registerTunnelIdentifierHandlers(context, regs);
         registerAfiSafi(context, regs);
-        registerNlriHandler(context, regs);
+        registerNlri(context, regs);
         registerExtendedCommunities(context, regs);
         registerAttributesHandler(context, regs);
+        NlriActivator.registerNlriParsers(regs);
         return regs;
     }
 }
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv4RIBSupport.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv4RIBSupport.java
new file mode 100644 (file)
index 0000000..f16691e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.protocol.bgp.mvpn.impl.nlri.Ipv4NlriHandler;
+import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.destination.DestinationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.MvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv4Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv4CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn.destination.MvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv4AdvertizedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv4.advertized._case.DestinationMvpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv4.advertized._case.DestinationMvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv4WithdrawnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+
+/**
+ * Ipv4 Mvpn RIBSupport.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class MvpnIpv4RIBSupport extends AbstractMvpnRIBSupport<MvpnRoutesIpv4Case> {
+    private static final MvpnRoutes EMPTY_CONTAINER
+            = new MvpnRoutesBuilder().setMvpnRoute(Collections.emptyList()).build();
+    private static final MvpnRoutesIpv4Case EMPTY_CASE
+            = new MvpnRoutesIpv4CaseBuilder().setMvpnRoutes(EMPTY_CONTAINER).build();
+    private static MvpnIpv4RIBSupport SINGLETON;
+
+    private MvpnIpv4RIBSupport(final BindingNormalizedNodeSerializer mappingService) {
+        super(mappingService,
+                MvpnRoutesIpv4Case.class,
+                Ipv4AddressFamily.class,
+                DestinationMvpn.QNAME,
+                MvpnDestination.QNAME);
+    }
+
+    static synchronized MvpnIpv4RIBSupport getInstance(final BindingNormalizedNodeSerializer mappingService) {
+        if (SINGLETON == null) {
+            SINGLETON = new MvpnIpv4RIBSupport(mappingService);
+        }
+        return SINGLETON;
+    }
+
+    private List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn
+            .destination.MvpnDestination> extractRoutes(final Collection<MapEntryNode> routes) {
+        return routes.stream().map(this::extractDestinations).collect(Collectors.toList());
+    }
+
+    private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn
+            .destination.MvpnDestination extractDestinations(final DataContainerNode<? extends PathArgument> mvpnDest) {
+        return new MvpnDestinationBuilder()
+                .setPrefix(new Ipv4Prefix(extractPrefix(mvpnDest)))
+                .setMvpnChoice(extractMvpnChoice(mvpnDest))
+                .setPathId(PathIdUtil.buildPathId(mvpnDest, routePathIdNid()))
+                .build();
+    }
+
+
+    @Override
+    protected DestinationType buildDestination(final Collection<MapEntryNode> routes) {
+        return new DestinationMvpnIpv4AdvertizedCaseBuilder().setDestinationMvpn(
+                new DestinationMvpnBuilder().setMvpnDestination(extractRoutes(routes)).build()).build();
+    }
+
+    @Override
+    protected DestinationType buildWithdrawnDestination(final Collection<MapEntryNode> routes) {
+        return new DestinationMvpnIpv4WithdrawnCaseBuilder().setDestinationMvpn(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update
+                        .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.mvpn.ipv4.withdrawn
+                        ._case.DestinationMvpnBuilder().setMvpnDestination(extractRoutes(routes)).build()).build();
+    }
+
+    @Override
+    public MvpnRoutesIpv4Case emptyRoutesCase() {
+        return EMPTY_CASE;
+    }
+
+    @Override
+    public MvpnRoutes emptyRoutesContainer() {
+        return EMPTY_CONTAINER;
+    }
+
+    @Override
+    public NodeIdentifierWithPredicates createRouteKey(final UnkeyedListEntryNode mvpn) {
+        final ByteBuf buffer = Unpooled.buffer();
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn.destination
+                .MvpnDestination dest = extractDestinations(mvpn);
+        Ipv4NlriHandler.serializeNlri(Collections.singletonList(dest), buffer);
+        final Optional<DataContainerChild<? extends PathArgument, ?>> maybePathIdLeaf =
+                mvpn.getChild(routePathIdNid());
+        return PathIdUtil.createNidKey(routeQName(), routeKeyQName(),
+                pathIdQName(), ByteArray.encodeBase64(buffer), maybePathIdLeaf);
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv6RIBSupport.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv6RIBSupport.java
new file mode 100644 (file)
index 0000000..af13889
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.protocol.bgp.mvpn.impl.nlri.Ipv6NlriHandler;
+import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.destination.DestinationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.MvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv6Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv6CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn.destination.MvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv6AdvertizedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv6.advertized._case.DestinationMvpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv6.advertized._case.DestinationMvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv6WithdrawnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+
+/**
+ * Ipv6 Mvpn RIBSupport.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class MvpnIpv6RIBSupport extends AbstractMvpnRIBSupport<MvpnRoutesIpv6Case> {
+    private static final MvpnRoutes EMPTY_CONTAINER = new MvpnRoutesBuilder()
+            .setMvpnRoute(Collections.emptyList()).build();
+    private static final MvpnRoutesIpv6Case EMPTY_CASE =
+            new MvpnRoutesIpv6CaseBuilder().setMvpnRoutes(EMPTY_CONTAINER).build();
+    private static MvpnIpv6RIBSupport SINGLETON;
+
+    private MvpnIpv6RIBSupport(final BindingNormalizedNodeSerializer mappingService) {
+        super(mappingService,
+                MvpnRoutesIpv6Case.class,
+                Ipv6AddressFamily.class,
+                DestinationMvpn.QNAME,
+                MvpnDestination.QNAME);
+    }
+
+    static synchronized MvpnIpv6RIBSupport getInstance(final BindingNormalizedNodeSerializer mappingService) {
+        if (SINGLETON == null) {
+            SINGLETON = new MvpnIpv6RIBSupport(mappingService);
+        }
+        return SINGLETON;
+    }
+
+    private List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn
+            .destination.MvpnDestination> extractRoutes(final Collection<MapEntryNode> routes) {
+        return routes.stream().map(this::extractDestination).collect(Collectors.toList());
+    }
+
+    private org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn
+            .destination.MvpnDestination extractDestination(final DataContainerNode<? extends PathArgument> mvpnDest) {
+        return new MvpnDestinationBuilder()
+                .setPrefix(new Ipv6Prefix(extractPrefix(mvpnDest)))
+                .setMvpnChoice(extractMvpnChoice(mvpnDest))
+                .setPathId(PathIdUtil.buildPathId(mvpnDest, routePathIdNid()))
+                .build();
+    }
+
+    @Override
+    protected DestinationType buildDestination(final Collection<MapEntryNode> routes) {
+        return new DestinationMvpnIpv6AdvertizedCaseBuilder().setDestinationMvpn(
+                new DestinationMvpnBuilder().setMvpnDestination(extractRoutes(routes)).build()).build();
+    }
+
+    @Override
+    protected DestinationType buildWithdrawnDestination(final Collection<MapEntryNode> routes) {
+        return new DestinationMvpnIpv6WithdrawnCaseBuilder().setDestinationMvpn(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update
+                        .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.mvpn.ipv6
+                        .withdrawn._case.DestinationMvpnBuilder().setMvpnDestination(extractRoutes(routes))
+                        .build()).build();
+    }
+
+    @Override
+    public MvpnRoutesIpv6Case emptyRoutesCase() {
+        return EMPTY_CASE;
+    }
+
+    @Override
+    public MvpnRoutes emptyRoutesContainer() {
+        return EMPTY_CONTAINER;
+    }
+
+    @Override
+    public NodeIdentifierWithPredicates createRouteKey(final UnkeyedListEntryNode mvpn) {
+        final ByteBuf buffer = Unpooled.buffer();
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn.destination
+                .MvpnDestination dest = extractDestination(mvpn);
+        Ipv6NlriHandler.serializeNlri(Collections.singletonList(dest), buffer);
+        final Optional<DataContainerChild<? extends PathArgument, ?>> maybePathIdLeaf =
+                mvpn.getChild(routePathIdNid());
+        return PathIdUtil.createNidKey(routeQName(), routeKeyQName(),
+                pathIdQName(), ByteArray.encodeBase64(buffer), maybePathIdLeaf);
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/RIBActivator.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/RIBActivator.java
new file mode 100644 (file)
index 0000000..2409882
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBExtensionProviderActivator;
+import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.McastVpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+
+/**
+ * RIBActivator.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class RIBActivator extends AbstractRIBExtensionProviderActivator {
+    @Override
+    protected List<AutoCloseable> startRIBExtensionProviderImpl(final RIBExtensionProviderContext context,
+            final BindingNormalizedNodeSerializer mappingService) {
+        return Lists.newArrayList(
+                context.registerRIBSupport(Ipv4AddressFamily.class, McastVpnSubsequentAddressFamily.class,
+                        MvpnIpv6RIBSupport.getInstance(mappingService)),
+                context.registerRIBSupport(Ipv6AddressFamily.class, McastVpnSubsequentAddressFamily.class,
+                        MvpnIpv4RIBSupport.getInstance(mappingService))
+        );
+    }
+}
index 06125eecc17a30c78be5837042444efc411a744a..4516f0e7541b03deea4662a19b4bf087f0f3d3a0 100644 (file)
@@ -22,7 +22,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn
  * @author Claudio D. Gasparini
  */
 final class CMulticastUtil {
-
     private CMulticastUtil() {
         throw new UnsupportedOperationException();
     }
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/Ipv4NlriHandler.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/Ipv4NlriHandler.java
new file mode 100644 (file)
index 0000000..b6ff76d
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl.nlri;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.bgp.mvpn.spi.pojo.nlri.SimpleMvpnNlriRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn.destination.MvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn.destination.MvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv4AdvertizedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv4AdvertizedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv4.advertized._case.DestinationMvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv4WithdrawnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv4WithdrawnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.NlriType;
+
+/**
+ * Handles Ipv4 Family nlri.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class Ipv4NlriHandler {
+    private Ipv4NlriHandler() {
+        throw new UnsupportedOperationException();
+    }
+
+    static DestinationMvpnIpv4AdvertizedCase parseIpv4ReachNlri(
+            final ByteBuf nlri,
+            final boolean addPathSupported) {
+        List<MvpnDestination> dests = new ArrayList<>();
+
+        while (nlri.isReadable()) {
+            final MvpnDestinationBuilder builder = new MvpnDestinationBuilder();
+            if (addPathSupported) {
+                builder.setPathId(PathIdUtil.readPathId(nlri));
+            }
+            final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
+            final int length = nlri.readUnsignedByte();
+            final ByteBuf nlriBuf = nlri.readSlice(length);
+            builder.setMvpnChoice(SimpleMvpnNlriRegistry.getInstance().parseMvpn(type, nlriBuf));
+            dests.add(builder.build());
+        }
+
+        return new DestinationMvpnIpv4AdvertizedCaseBuilder().setDestinationMvpn(
+                new DestinationMvpnBuilder().setMvpnDestination(dests).build()).build();
+    }
+
+    static DestinationMvpnIpv4WithdrawnCase parseIpv4UnreachNlri(
+            final ByteBuf nlri,
+            final boolean addPathSupported) {
+        List<MvpnDestination> dests = new ArrayList<>();
+
+        while (nlri.isReadable()) {
+            final MvpnDestinationBuilder builder = new MvpnDestinationBuilder();
+            if (addPathSupported) {
+                builder.setPathId(PathIdUtil.readPathId(nlri));
+            }
+            final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
+            final int length = nlri.readUnsignedByte();
+            final ByteBuf nlriBuf = nlri.readSlice(length);
+            builder.setMvpnChoice(SimpleMvpnNlriRegistry.getInstance().parseMvpn(type, nlriBuf));
+            dests.add(builder.build());
+        }
+
+        return new DestinationMvpnIpv4WithdrawnCaseBuilder().setDestinationMvpn(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update
+                        .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.mvpn.ipv4
+                        .withdrawn._case.DestinationMvpnBuilder().setMvpnDestination(dests).build()).build();
+    }
+
+    public static void serializeNlri(final List<MvpnDestination> destinationList, final ByteBuf output) {
+        ByteBuf nlriOutput = null;
+        for (final MvpnDestination dest : destinationList) {
+            final ByteBuf nlriCommon = Unpooled.buffer();
+            nlriOutput = SimpleMvpnNlriRegistry.getInstance().serializeMvpn(dest.getMvpnChoice(), nlriCommon);
+        }
+        output.writeBytes(nlriOutput);
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/Ipv6NlriHandler.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/Ipv6NlriHandler.java
new file mode 100644 (file)
index 0000000..4fd7c8b
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl.nlri;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.bgp.mvpn.spi.pojo.nlri.SimpleMvpnNlriRegistry;
+import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn.destination.MvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn.destination.MvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv6AdvertizedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv6AdvertizedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv6.advertized._case.DestinationMvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv6WithdrawnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv6WithdrawnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.NlriType;
+
+/**
+ * Handles Ipv6 Family nlri.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class Ipv6NlriHandler {
+    private Ipv6NlriHandler() {
+        throw new UnsupportedOperationException();
+    }
+
+    static DestinationMvpnIpv6AdvertizedCase parseIpv6ReachNlri(
+            final ByteBuf nlri,
+            final boolean addPathSupported) {
+        List<MvpnDestination> dests = new ArrayList<>();
+
+        while (nlri.isReadable()) {
+            final MvpnDestinationBuilder builder = new MvpnDestinationBuilder();
+            if (addPathSupported) {
+                builder.setPathId(PathIdUtil.readPathId(nlri));
+            }
+            final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
+            final int length = nlri.readUnsignedByte();
+            final ByteBuf nlriBuf = nlri.readSlice(length);
+            builder.setMvpnChoice(SimpleMvpnNlriRegistry.getInstance().parseMvpn(type, nlriBuf));
+            dests.add(builder.build());
+        }
+
+        return new DestinationMvpnIpv6AdvertizedCaseBuilder().setDestinationMvpn(
+                new DestinationMvpnBuilder().setMvpnDestination(dests).build()).build();
+    }
+
+    static DestinationMvpnIpv6WithdrawnCase parseIpv6UnreachNlri(
+            final ByteBuf nlri,
+            final boolean addPathSupported) {
+        List<MvpnDestination> dests = new ArrayList<>();
+
+        while (nlri.isReadable()) {
+            final MvpnDestinationBuilder builder = new MvpnDestinationBuilder();
+            if (addPathSupported) {
+                builder.setPathId(PathIdUtil.readPathId(nlri));
+            }
+            final NlriType type = NlriType.forValue(nlri.readUnsignedByte());
+            final int length = nlri.readUnsignedByte();
+            final ByteBuf nlriBuf = nlri.readSlice(length);
+            builder.setMvpnChoice(SimpleMvpnNlriRegistry.getInstance().parseMvpn(type, nlriBuf));
+            dests.add(builder.build());
+        }
+
+        return new DestinationMvpnIpv6WithdrawnCaseBuilder().setDestinationMvpn(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update
+                        .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.mvpn.ipv6.withdrawn
+                        ._case.DestinationMvpnBuilder().setMvpnDestination(dests).build()).build();
+    }
+
+    public static void serializeNlri(final List<MvpnDestination> destinationList, final ByteBuf output) {
+        ByteBuf nlriOutput = null;
+        for (final MvpnDestination dest : destinationList) {
+            final ByteBuf nlriCommon = Unpooled.buffer();
+            nlriOutput = SimpleMvpnNlriRegistry.getInstance().serializeMvpn(dest.getMvpnChoice(), nlriCommon);
+        }
+        output.writeBytes(nlriOutput);
+    }
+}
diff --git a/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/MvpnNlriHandler.java b/bgp/mvpn/src/main/java/org/opendaylight/protocol/bgp/mvpn/impl/nlri/MvpnNlriHandler.java
new file mode 100644 (file)
index 0000000..b1e8d56
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl.nlri;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupportUtil;
+import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
+import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.destination.DestinationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv4AdvertizedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv4WithdrawnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv6AdvertizedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv6WithdrawnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * https://tools.ietf.org/html/rfc6514#section-4.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class MvpnNlriHandler implements NlriParser, NlriSerializer {
+    @Override
+    public void parseNlri(
+            final ByteBuf nlri,
+            final MpReachNlriBuilder builder,
+            final PeerSpecificParserConstraint constraint) throws BGPParsingException {
+        if (!nlri.isReadable()) {
+            return;
+        }
+        final Class<? extends AddressFamily> afi = builder.getAfi();
+        final boolean mPathSupported = MultiPathSupportUtil.isTableTypeSupported(constraint,
+                new BgpTableTypeImpl(builder.getAfi(), builder.getSafi()));
+
+        DestinationType dst = null;
+        if (afi == Ipv4AddressFamily.class) {
+            dst = Ipv4NlriHandler.parseIpv4ReachNlri(nlri, mPathSupported);
+        } else if (afi == Ipv6AddressFamily.class) {
+            dst = Ipv6NlriHandler.parseIpv6ReachNlri(nlri, mPathSupported);
+        }
+
+        builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(dst).build());
+    }
+
+
+    @Override
+    public void parseNlri(
+            final ByteBuf nlri,
+            final MpUnreachNlriBuilder builder,
+            final PeerSpecificParserConstraint constraint) throws BGPParsingException {
+        if (!nlri.isReadable()) {
+            return;
+        }
+        final Class<? extends AddressFamily> afi = builder.getAfi();
+        final boolean mPathSupported = MultiPathSupportUtil.isTableTypeSupported(constraint,
+                new BgpTableTypeImpl(builder.getAfi(), builder.getSafi()));
+
+        DestinationType dst = null;
+        if (afi == Ipv4AddressFamily.class) {
+            dst = Ipv4NlriHandler.parseIpv4UnreachNlri(nlri, mPathSupported);
+        } else if (afi == Ipv6AddressFamily.class) {
+            dst = Ipv6NlriHandler.parseIpv6UnreachNlri(nlri, mPathSupported);
+        }
+
+        builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(dst).build());
+    }
+
+    @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 DestinationMvpnIpv4AdvertizedCase) {
+                final DestinationMvpnIpv4AdvertizedCase reach
+                        = (DestinationMvpnIpv4AdvertizedCase) routes.getDestinationType();
+                Ipv4NlriHandler.serializeNlri(reach.getDestinationMvpn().getMvpnDestination(),
+                        byteAggregator);
+            } else if (routes != null && routes.getDestinationType() instanceof DestinationMvpnIpv6AdvertizedCase) {
+                final DestinationMvpnIpv6AdvertizedCase reach
+                        = (DestinationMvpnIpv6AdvertizedCase) routes.getDestinationType();
+                Ipv6NlriHandler.serializeNlri(reach.getDestinationMvpn().getMvpnDestination(),
+                        byteAggregator);
+            }
+        } else if (pathAttributes2 != null) {
+            final WithdrawnRoutes withdrawnRoutes = pathAttributes2.getMpUnreachNlri().getWithdrawnRoutes();
+            if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType()
+                    instanceof DestinationMvpnIpv4WithdrawnCase) {
+                final DestinationMvpnIpv4WithdrawnCase reach
+                        = (DestinationMvpnIpv4WithdrawnCase) withdrawnRoutes.getDestinationType();
+                Ipv4NlriHandler.serializeNlri(reach.getDestinationMvpn().getMvpnDestination(),
+                        byteAggregator);
+            } else if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType()
+                    instanceof DestinationMvpnIpv6WithdrawnCase) {
+                final DestinationMvpnIpv6WithdrawnCase reach
+                        = (DestinationMvpnIpv6WithdrawnCase) withdrawnRoutes.getDestinationType();
+                Ipv6NlriHandler.serializeNlri(reach.getDestinationMvpn().getMvpnDestination(),
+                        byteAggregator);
+            }
+        }
+    }
+}
diff --git a/bgp/mvpn/src/main/resources/META-INF/services/org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderActivator b/bgp/mvpn/src/main/resources/META-INF/services/org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderActivator
new file mode 100644 (file)
index 0000000..5b9c8d4
--- /dev/null
@@ -0,0 +1,6 @@
+# Copyright (c) 2018 AT&T Intellectual Property. 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
+org.opendaylight.protocol.bgp.mvpn.impl.RIBActivator
\ No newline at end of file
index 24f9f7045339167942d25100e73d3265af2f6391..1b7ceb36c2aa3bb5534c7949ec5f80f0827e1ad0 100644 (file)
            xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
 
   <bean id="BGPActivator" class="org.opendaylight.protocol.bgp.mvpn.impl.BGPActivator"/>
-
   <service ref="BGPActivator" interface="org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderActivator"
           odl:type="org.opendaylight.protocol.bgp.mvpn.impl.BGPActivator"/>
 
   <bean id="TableTypeActivator" class="org.opendaylight.protocol.bgp.mvpn.impl.TableTypeActivator"/>
-
   <service ref="TableTypeActivator"
            interface="org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryProviderActivator"
            odl:type="org.opendaylight.protocol.bgp.mvpn.impl.TableTypeActivator"/>
+
+  <bean id="RIBActivator" class="org.opendaylight.protocol.bgp.mvpn.impl.RIBActivator"/>
+  <service ref="RIBActivator" interface="org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderActivator"
+           odl:type="org.opendaylight.protocol.bgp.mvpn.impl.RIBActivator"/>
 </blueprint>
\ No newline at end of file
index 95cd89dfa88987189c18110520645f7208d5cd29..bf313944f2b84e89e2a3f6a56e558337da118e99 100644 (file)
@@ -16,7 +16,7 @@ module bgp-mvpn-ipv4 {
     grouping mvpn-destination {
         list mvpn-destination {
             uses mvpn:mvpn;
-            leaf ipv4-prefix {
+            leaf prefix {
                 type inet:ipv4-prefix;
             }
             uses bgp-msg:path-id-grouping;
@@ -25,8 +25,7 @@ module bgp-mvpn-ipv4 {
 
     augment "/bgp-msg:update/bgp-msg:attributes/bgp-mp:mp-reach-nlri/bgp-mp:advertized-routes/bgp-mp:destination-type" {
         case destination-mvpn-ipv4-advertized-case {
-            container destination-advertized-mvpn {
-                when "../../afi = ipv4";
+            container destination-mvpn {
                 uses mvpn-destination;
             }
         }
@@ -34,8 +33,7 @@ module bgp-mvpn-ipv4 {
 
     augment "/bgp-msg:update/bgp-msg:attributes/bgp-mp:mp-unreach-nlri/bgp-mp:withdrawn-routes/bgp-mp:destination-type" {
         case destination-mvpn-ipv4-withdrawn-case {
-            container destination-withdrawn-mvpn {
-                 when "../../afi = ipv4";
+            container destination-mvpn {
                 uses mvpn-destination;
             }
         }
index bba8097a35d5ab49d40c08c38af4234567e406d0..c9cc62d9376f0b28c72441432b7f5b000503c40d 100644 (file)
@@ -16,7 +16,7 @@ module bgp-mvpn-ipv6 {
     grouping mvpn-destination {
         list mvpn-destination {
             uses mvpn:mvpn;
-            leaf ipv6-prefix {
+            leaf prefix {
                 type inet:ipv6-prefix;
             }
             uses bgp-msg:path-id-grouping;
@@ -25,8 +25,7 @@ module bgp-mvpn-ipv6 {
 
     augment "/bgp-msg:update/bgp-msg:attributes/bgp-mp:mp-reach-nlri/bgp-mp:advertized-routes/bgp-mp:destination-type" {
         case destination-mvpn-ipv6-advertized-case {
-            container destination-advertized-mvpn {
-                when "../../afi = ipv6";
+            container destination-mvpn {
                 uses mvpn-destination;
             }
         }
@@ -34,8 +33,7 @@ module bgp-mvpn-ipv6 {
 
     augment "/bgp-msg:update/bgp-msg:attributes/bgp-mp:mp-unreach-nlri/bgp-mp:withdrawn-routes/bgp-mp:destination-type" {
         case destination-mvpn-ipv6-withdrawn-case {
-            container destination-withdrawn-mvpn {
-                 when "../../afi = ipv6";
+            container destination-mvpn {
                 uses mvpn-destination;
             }
         }
index 566e6f3d41cafdcea6f5967e1ebe6c7d69755333..49685ecac3e271f01073520f74a50ff7ba9f0561 100644 (file)
@@ -31,7 +31,9 @@ module bgp-mvpn {
     }
 
     identity mcast-vpn-subsequent-address-family {
+        description "SAFI 5 MCAST-VPN";
         reference "https://www.iana.org/assignments/safi-namespace/safi-namespace.xhtml";
+
         base bgp-t:subsequent-address-family;
     }
 
@@ -146,8 +148,6 @@ module bgp-mvpn {
             description "https://tools.ietf.org/html/rfc6514#section-4.5";
 
             uses multicast-source-rd-grouping;
-            uses source-as-grouping;
-
             leaf multicast-group {
                 type inet:ip-address;
             }
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/BGPActivatorTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/BGPActivatorTest.java
new file mode 100644 (file)
index 0000000..6d44422
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.opendaylight.protocol.bgp.mvpn.impl.BGPActivator.MVPN_SAFI;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.SimpleBGPExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.McastVpnSubsequentAddressFamily;
+
+public final class BGPActivatorTest {
+    @Test
+    public void testActivator() {
+        final BGPActivator act = new BGPActivator();
+        final BGPExtensionProviderContext context = new SimpleBGPExtensionProviderContext();
+        assertNull(context.getSubsequentAddressFamilyRegistry().classForFamily(MVPN_SAFI));
+        act.start(context);
+        assertEquals(McastVpnSubsequentAddressFamily.class, context.getSubsequentAddressFamilyRegistry()
+                .classForFamily(MVPN_SAFI));
+        act.close();
+    }
+}
\ No newline at end of file
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv4RIBSupportTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv4RIBSupportTest.java
new file mode 100644 (file)
index 0000000..9a33989
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupportTest;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.PathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv4Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv4CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn.destination.MvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.mvpn.destination.MvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv4AdvertizedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv4AdvertizedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv4.advertized._case.DestinationMvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv4WithdrawnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv4WithdrawnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.inter.as.i.pmsi.a.d.grouping.InterAsIPmsiADBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.MvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.mvpn.choice.InterAsIPmsiADCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRouteKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RdIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
+
+@Ignore
+public class MvpnIpv4RIBSupportTest extends AbstractRIBSupportTest<MvpnRoute> {
+    private static final MvpnRouteKey ROUTE_KEY;
+    private static final MvpnRoute ROUTE;
+    private static final IpPrefix PREFIX = new IpPrefix(new Ipv4Prefix("127.0.0.1/32"));
+    private static final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn
+            .routes.MvpnRoutes MVPN_ROUTES;
+    private static final MvpnChoice MVPN = new InterAsIPmsiADCaseBuilder().setInterAsIPmsiAD(
+            new InterAsIPmsiADBuilder()
+                    .setSourceAs(new AsNumber(1L))
+                    .setRouteDistinguisher(new RouteDistinguisher(new RdIpv4("1.2.3.4:258")))
+                    .build()).build();
+    private static final PathId PATH_ID = new PathId(0L);
+    private static final MvpnDestination MVPN_DESTINATION = new MvpnDestinationBuilder()
+            .setMvpnChoice(MVPN)
+            .setPrefix(PREFIX.getIpv4Prefix())
+            .setPathId(PATH_ID)
+            .build();
+    private static final DestinationMvpnIpv4AdvertizedCase REACH_NLRI = new DestinationMvpnIpv4AdvertizedCaseBuilder()
+            .setDestinationMvpn(new DestinationMvpnBuilder()
+                    .setMvpnDestination(Collections.singletonList(MVPN_DESTINATION)).build()).build();
+    private static final DestinationMvpnIpv4WithdrawnCase UNREACH_NLRI = new DestinationMvpnIpv4WithdrawnCaseBuilder()
+            .setDestinationMvpn(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv4
+                    .rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.mvpn
+                    .ipv4.withdrawn._case.DestinationMvpnBuilder()
+                    .setMvpnDestination(Collections.singletonList(MVPN_DESTINATION)).build()).build();
+
+    static {
+        ROUTE_KEY = new MvpnRouteKey(PATH_ID, "AgwAAQECAwQBAgAAAAE=");
+        ROUTE = new MvpnRouteBuilder()
+                .setRouteKey(ROUTE_KEY.getRouteKey())
+                .setPrefix(PREFIX)
+                .setPathId(ROUTE_KEY.getPathId())
+                .setAttributes(ATTRIBUTES)
+                .setMvpnChoice(MVPN)
+                .build();
+        MVPN_ROUTES = new MvpnRoutesBuilder().setMvpnRoute(Collections.singletonList(ROUTE)).build();
+    }
+
+    private MvpnIpv4RIBSupport ribSupport;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        ribSupport = MvpnIpv4RIBSupport.getInstance(this.mappingService);
+        setUpTestCustomizer(ribSupport);
+        NlriActivator.registerNlriParsers(new ArrayList<>());
+    }
+
+    @Test
+    public void testDeleteRoutes() {
+        final ContainerNode withdraw = createNlriWithDrawnRoute(UNREACH_NLRI);
+        this.ribSupport.deleteRoutes(this.tx, getTablePath(), withdraw);
+        final InstanceIdentifier<MvpnRoute> instanceIdentifier = this.deletedRoutes.get(0);
+        assertEquals(ROUTE_KEY, instanceIdentifier.firstKeyOf(MvpnRoute.class));
+    }
+
+    @Test
+    public void testPutRoutes() {
+        this.ribSupport.putRoutes(this.tx, getTablePath(), createNlriAdvertiseRoute(REACH_NLRI), createAttributes());
+        final MvpnRoute route = (MvpnRoute) this.insertedRoutes.get(0).getValue();
+        assertEquals(ROUTE, route);
+    }
+
+
+    @Test
+    public void testEmptyRoute() {
+        final Routes empty = new MvpnRoutesIpv4CaseBuilder().setMvpnRoutes(new MvpnRoutesBuilder()
+                .setMvpnRoute(Collections.emptyList()).build()).build();
+        final ChoiceNode expected = createRoutes(empty);
+        assertEquals(expected, this.ribSupport.emptyRoutes());
+    }
+
+    @Test
+    public void testBuildMpUnreachNlriUpdate() {
+        final Collection<MapEntryNode> routes = createRoutes(MVPN_ROUTES);
+        final Update update = this.ribSupport.buildUpdate(Collections.emptyList(), routes, ATTRIBUTES);
+        assertEquals(UNREACH_NLRI, update.getAttributes().getAugmentation(Attributes2.class).getMpUnreachNlri()
+                .getWithdrawnRoutes().getDestinationType());
+        assertNull(update.getAttributes().getAugmentation(Attributes1.class));
+    }
+
+    @Test
+    public void testBuildMpReachNlriUpdate() {
+        final Collection<MapEntryNode> routes = createRoutes(MVPN_ROUTES);
+        final Update update = this.ribSupport.buildUpdate(routes, Collections.emptyList(), ATTRIBUTES);
+        assertEquals(REACH_NLRI, update.getAttributes().getAugmentation(Attributes1.class).getMpReachNlri()
+                .getAdvertizedRoutes().getDestinationType());
+        assertNull(update.getAttributes().getAugmentation(Attributes2.class));
+    }
+
+    @Test
+    public void testCacheableNlriObjects() {
+        assertEquals(ImmutableSet.of(), this.ribSupport.cacheableNlriObjects());
+    }
+
+    @Test
+    public void testCacheableAttributeObjects() {
+        assertEquals(ImmutableSet.of(), this.ribSupport.cacheableAttributeObjects());
+    }
+
+    @Test
+    public void testRouteIdAddPath() {
+        assertEquals(ROUTE_KEY, this.ribSupport.createRouteListKey(ROUTE_KEY.getPathId().getValue(),
+                ROUTE_KEY.getRouteKey()));
+    }
+
+    @Test
+    public void testRoutePath() {
+        final YangInstanceIdentifier.NodeIdentifierWithPredicates prefixNii = createRouteNIWP(MVPN_ROUTES);
+        final YangInstanceIdentifier expected = getRoutePath().node(prefixNii);
+        final YangInstanceIdentifier actual = this.ribSupport.routePath(getTablePath().node(Routes.QNAME), prefixNii);
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testRouteAttributesIdentifier() {
+        assertEquals(new YangInstanceIdentifier.NodeIdentifier(
+                        Attributes.QNAME.withModule(BindingReflections.getQNameModule(MvpnRoutesIpv4Case.class))),
+                this.ribSupport.routeAttributesIdentifier());
+    }
+
+    @Test
+    public void testRoutesCaseClass() {
+        assertEquals(MvpnRoutesIpv4Case.class, this.ribSupport.routesCaseClass());
+    }
+
+    @Test
+    public void testRoutesContainerClass() {
+        assertEquals(MvpnRoutes.class, this.ribSupport.routesContainerClass());
+    }
+
+    @Test
+    public void testRoutesListClass() {
+        assertEquals(MvpnRoute.class, this.ribSupport.routesListClass());
+    }
+
+    @Test
+    public void testChangedRoutes() {
+        final Routes emptyCase = new MvpnRoutesIpv4CaseBuilder().build();
+        DataTreeCandidateNode tree = DataTreeCandidates.fromNormalizedNode(getRoutePath(),
+                createRoutes(emptyCase)).getRootNode();
+        assertTrue(this.ribSupport.changedRoutes(tree).isEmpty());
+
+        final Routes emptyRoutes
+                = new MvpnRoutesIpv4CaseBuilder().setMvpnRoutes(new MvpnRoutesBuilder().build()).build();
+        tree = DataTreeCandidates.fromNormalizedNode(getRoutePath(), createRoutes(emptyRoutes)).getRootNode();
+        assertTrue(this.ribSupport.changedRoutes(tree).isEmpty());
+
+        final Routes routes = new MvpnRoutesIpv4CaseBuilder().setMvpnRoutes(MVPN_ROUTES).build();
+        tree = DataTreeCandidates.fromNormalizedNode(getRoutePath(), createRoutes(routes)).getRootNode();
+        final Collection<DataTreeCandidateNode> result = this.ribSupport.changedRoutes(tree);
+        assertFalse(result.isEmpty());
+    }
+}
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv6RIBSupportTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/MvpnIpv6RIBSupportTest.java
new file mode 100644 (file)
index 0000000..56d282e
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableSet;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.Collection;
+import java.util.Collections;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupportTest;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.PathId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv6Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.bgp.rib.rib.loc.rib.tables.routes.MvpnRoutesIpv6CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn.destination.MvpnDestination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.mvpn.destination.MvpnDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv6AdvertizedCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationMvpnIpv6AdvertizedCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.mvpn.ipv6.advertized._case.DestinationMvpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv6WithdrawnCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6.rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationMvpnIpv6WithdrawnCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.inter.as.i.pmsi.a.d.grouping.InterAsIPmsiADBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.MvpnChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.mvpn.choice.InterAsIPmsiADCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.MvpnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.routes.mvpn.routes.MvpnRouteKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RdIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
+
+@Ignore
+public final class MvpnIpv6RIBSupportTest extends AbstractRIBSupportTest<MvpnRoute> {
+    private static final MvpnRouteKey ROUTE_KEY;
+    private static final MvpnRoute ROUTE;
+    private static final IpPrefix PREFIX = new IpPrefix(new Ipv6Prefix("2001:db8:1:1::/64"));
+    private static final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn
+            .routes.MvpnRoutes MVPN_ROUTES;
+    private static final MvpnChoice MVPN = new InterAsIPmsiADCaseBuilder().setInterAsIPmsiAD(
+            new InterAsIPmsiADBuilder()
+                    .setSourceAs(new AsNumber(1L))
+                    .setRouteDistinguisher(new RouteDistinguisher(new RdIpv4("1.2.3.4:258")))
+                    .build()).build();
+    private static final PathId PATH_ID = new PathId(0L);
+    private static final MvpnDestination MVPN_DESTINATION = new MvpnDestinationBuilder()
+            .setMvpnChoice(MVPN)
+            .setPrefix(PREFIX.getIpv6Prefix())
+            .setPathId(PATH_ID)
+            .build();
+    private static final DestinationMvpnIpv6AdvertizedCase REACH_NLRI = new DestinationMvpnIpv6AdvertizedCaseBuilder()
+            .setDestinationMvpn(new DestinationMvpnBuilder()
+                    .setMvpnDestination(Collections.singletonList(MVPN_DESTINATION)).build()).build();
+    private static final DestinationMvpnIpv6WithdrawnCase UNREACH_NLRI = new DestinationMvpnIpv6WithdrawnCaseBuilder()
+            .setDestinationMvpn(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.ipv6
+                    .rev180417.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.mvpn
+                    .ipv6.withdrawn._case.DestinationMvpnBuilder()
+                    .setMvpnDestination(Collections.singletonList(MVPN_DESTINATION)).build()).build();
+
+    static {
+        final ByteBuf buffer = Unpooled.buffer();
+        ROUTE_KEY = new MvpnRouteKey(PATH_ID, ByteArray.encodeBase64(buffer));
+        ROUTE = new MvpnRouteBuilder()
+                .setRouteKey(ROUTE_KEY.getRouteKey())
+                .setPrefix(PREFIX)
+                .setPathId(ROUTE_KEY.getPathId())
+                .setAttributes(ATTRIBUTES)
+                .setMvpnChoice(MVPN)
+                .build();
+        MVPN_ROUTES = new MvpnRoutesBuilder().setMvpnRoute(Collections.singletonList(ROUTE)).build();
+    }
+
+    private MvpnIpv6RIBSupport ribSupport;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        ribSupport = MvpnIpv6RIBSupport.getInstance(this.mappingService);
+        setUpTestCustomizer(ribSupport);
+    }
+
+    @Test
+    public void testDeleteRoutes() {
+        final ContainerNode withdraw = createNlriWithDrawnRoute(UNREACH_NLRI);
+        this.ribSupport.deleteRoutes(this.tx, getTablePath(), withdraw);
+        final InstanceIdentifier<MvpnRoute> instanceIdentifier = this.deletedRoutes.get(0);
+        assertEquals(ROUTE_KEY, instanceIdentifier.firstKeyOf(MvpnRoute.class));
+    }
+
+    @Test
+    public void testPutRoutes() {
+        this.ribSupport.putRoutes(this.tx, getTablePath(), createNlriAdvertiseRoute(REACH_NLRI), createAttributes());
+        final MvpnRoute route = (MvpnRoute) this.insertedRoutes.get(0).getValue();
+        assertEquals(ROUTE, route);
+    }
+
+
+    @Test
+    public void testEmptyRoute() {
+        final Routes empty = new MvpnRoutesIpv6CaseBuilder().setMvpnRoutes(new MvpnRoutesBuilder()
+                .setMvpnRoute(Collections.emptyList()).build()).build();
+        final ChoiceNode expected = createRoutes(empty);
+        assertEquals(expected, this.ribSupport.emptyRoutes());
+    }
+
+    @Test
+    public void testBuildMpUnreachNlriUpdate() {
+        final Collection<MapEntryNode> routes = createRoutes(MVPN_ROUTES);
+        final Update update = this.ribSupport.buildUpdate(Collections.emptyList(), routes, ATTRIBUTES);
+        assertEquals(UNREACH_NLRI, update.getAttributes().getAugmentation(Attributes2.class).getMpUnreachNlri()
+                .getWithdrawnRoutes().getDestinationType());
+        assertNull(update.getAttributes().getAugmentation(Attributes1.class));
+    }
+
+    @Test
+    public void testBuildMpReachNlriUpdate() {
+        final Collection<MapEntryNode> routes = createRoutes(MVPN_ROUTES);
+        final Update update = this.ribSupport.buildUpdate(routes, Collections.emptyList(), ATTRIBUTES);
+        assertEquals(REACH_NLRI, update.getAttributes().getAugmentation(Attributes1.class).getMpReachNlri()
+                .getAdvertizedRoutes().getDestinationType());
+        assertNull(update.getAttributes().getAugmentation(Attributes2.class));
+    }
+
+    @Test
+    public void testCacheableNlriObjects() {
+        assertEquals(ImmutableSet.of(), this.ribSupport.cacheableNlriObjects());
+    }
+
+    @Test
+    public void testCacheableAttributeObjects() {
+        assertEquals(ImmutableSet.of(), this.ribSupport.cacheableAttributeObjects());
+    }
+
+    @Test
+    public void testRouteIdAddPath() {
+        assertEquals(ROUTE_KEY, this.ribSupport.createRouteListKey(ROUTE_KEY.getPathId().getValue(),
+                ROUTE_KEY.getRouteKey()));
+    }
+
+    @Test
+    public void testRoutePath() {
+        final NodeIdentifierWithPredicates prefixNii = createRouteNIWP(MVPN_ROUTES);
+        final YangInstanceIdentifier expected = getRoutePath().node(prefixNii);
+        final YangInstanceIdentifier actual = this.ribSupport.routePath(getTablePath().node(Routes.QNAME), prefixNii);
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testRouteAttributesIdentifier() {
+        assertEquals(new NodeIdentifier(
+                        Attributes.QNAME.withModule(BindingReflections.getQNameModule(MvpnRoutesIpv6Case.class))),
+                this.ribSupport.routeAttributesIdentifier());
+    }
+
+    @Test
+    public void testRoutesCaseClass() {
+        assertEquals(MvpnRoutesIpv6Case.class, this.ribSupport.routesCaseClass());
+    }
+
+    @Test
+    public void testRoutesContainerClass() {
+        assertEquals(MvpnRoutes.class, this.ribSupport.routesContainerClass());
+    }
+
+    @Test
+    public void testRoutesListClass() {
+        assertEquals(MvpnRoute.class, this.ribSupport.routesListClass());
+    }
+
+    @Test
+    public void testChangedRoutes() {
+        final Routes emptyCase = new MvpnRoutesIpv6CaseBuilder().build();
+        DataTreeCandidateNode tree = DataTreeCandidates.fromNormalizedNode(getRoutePath(),
+                createRoutes(emptyCase)).getRootNode();
+        assertTrue(this.ribSupport.changedRoutes(tree).isEmpty());
+
+        final Routes emptyRoutes
+                = new MvpnRoutesIpv6CaseBuilder().setMvpnRoutes(new MvpnRoutesBuilder().build()).build();
+        tree = DataTreeCandidates.fromNormalizedNode(getRoutePath(), createRoutes(emptyRoutes)).getRootNode();
+        assertTrue(this.ribSupport.changedRoutes(tree).isEmpty());
+
+        final Routes routes = new MvpnRoutesIpv6CaseBuilder().setMvpnRoutes(MVPN_ROUTES).build();
+        tree = DataTreeCandidates.fromNormalizedNode(getRoutePath(), createRoutes(routes)).getRootNode();
+        final Collection<DataTreeCandidateNode> result = this.ribSupport.changedRoutes(tree);
+        assertFalse(result.isEmpty());
+    }
+}
\ No newline at end of file
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/RIBActivatorTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/RIBActivatorTest.java
new file mode 100644 (file)
index 0000000..e96b401
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBActivatorTest;
+import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
+import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.McastVpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+
+public class RIBActivatorTest extends AbstractRIBActivatorTest {
+    @Test
+    public void testRIBActivator() {
+        final RIBActivator ribAct = new RIBActivator();
+        final RIBExtensionProviderContext context = new SimpleRIBExtensionProviderContext();
+        assertNull(context.getRIBSupport(Ipv4AddressFamily.class, McastVpnSubsequentAddressFamily.class));
+        assertNull(context.getRIBSupport(Ipv6AddressFamily.class, McastVpnSubsequentAddressFamily.class));
+        ribAct.startRIBExtensionProvider(context, this.mappingService);
+        assertNotNull(context.getRIBSupport(Ipv4AddressFamily.class, McastVpnSubsequentAddressFamily.class));
+        assertNotNull(context.getRIBSupport(Ipv6AddressFamily.class, McastVpnSubsequentAddressFamily.class));
+        ribAct.close();
+    }
+}
\ No newline at end of file
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/TableTypeActivatorTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/impl/TableTypeActivatorTest.java
new file mode 100644 (file)
index 0000000..237e20b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.impl;
+
+import java.util.Optional;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.openconfig.spi.SimpleBGPTableTypeRegistryProvider;
+import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.McastVpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.IPV4MCASTVPN;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.IPV6MCASTVPN;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
+
+public final class TableTypeActivatorTest {
+
+    private static final BgpTableType MVPN_IPV4 = new BgpTableTypeImpl(
+            Ipv4AddressFamily.class, McastVpnSubsequentAddressFamily.class);
+    private static final BgpTableType MVPN_IPV6 = new BgpTableTypeImpl(
+            Ipv6AddressFamily.class, McastVpnSubsequentAddressFamily.class);
+
+    @Test
+    public void testActivator() {
+        final TableTypeActivator tableTypeActivator = new TableTypeActivator();
+        final SimpleBGPTableTypeRegistryProvider registry = new SimpleBGPTableTypeRegistryProvider();
+        tableTypeActivator.startBGPTableTypeRegistryProvider(registry);
+
+        final Optional<Class<? extends AfiSafiType>> afiSafiType4 = registry.getAfiSafiType(MVPN_IPV4);
+        Assert.assertEquals(IPV4MCASTVPN.class, afiSafiType4.get());
+        final Optional<Class<? extends AfiSafiType>> afiSafiType6 = registry.getAfiSafiType(MVPN_IPV6);
+        Assert.assertEquals(IPV6MCASTVPN.class, afiSafiType6.get());
+
+        final Optional<BgpTableType> tableType4 = registry.getTableType(IPV4MCASTVPN.class);
+        Assert.assertEquals(MVPN_IPV4, tableType4.get());
+        final Optional<BgpTableType> tableType6 = registry.getTableType(IPV6MCASTVPN.class);
+        Assert.assertEquals(MVPN_IPV6, tableType6.get());
+
+        tableTypeActivator.stopBGPTableTypeRegistryProvider();
+        tableTypeActivator.close();
+    }
+}
\ No newline at end of file
diff --git a/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/spi/pojo/nlri/SimpleMvpnNlriRegistryTest.java b/bgp/mvpn/src/test/java/org/opendaylight/protocol/bgp/mvpn/spi/pojo/nlri/SimpleMvpnNlriRegistryTest.java
new file mode 100644 (file)
index 0000000..4040c93
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.mvpn.spi.pojo.nlri;
+
+import static org.junit.Assert.assertEquals;
+
+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.mvpn.impl.NlriActivator;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.NlriType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mvpn.rev180417.mvpn.MvpnChoice;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+
+public final class SimpleMvpnNlriRegistryTest {
+    @Before
+    public void setUp() {
+        NlriActivator.registerNlriParsers(new ArrayList<>());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void registryParseTest() {
+        SimpleMvpnNlriRegistry.getInstance().parseMvpn(NlriType.InterAsIPmsiAD, null);
+    }
+
+    @Test
+    public void registryNullTest() {
+        final ByteBuf body = Unpooled.buffer();
+        SimpleMvpnNlriRegistry.getInstance().serializeMvpn(new NotRegistered(), body);
+        assertEquals(0, body.readableBytes());
+    }
+
+    private class NotRegistered implements MvpnChoice {
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return NotRegistered.class;
+        }
+    }
+
+}
\ No newline at end of file
index 65a389c3ca9a581db0000a697447989803dfd215..fad8797dd7a90f7780c92e99175c92907f8446b2 100644 (file)
@@ -34,10 +34,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mult
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.BgpRib;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.RibId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.Rib;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.RibKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesBuilder;
@@ -54,6 +52,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
@@ -83,6 +82,8 @@ public abstract class AbstractRIBSupport<
     private static final NodeIdentifier ADVERTISED_ROUTES = new NodeIdentifier(AdvertizedRoutes.QNAME);
     private static final NodeIdentifier WITHDRAWN_ROUTES = new NodeIdentifier(WithdrawnRoutes.QNAME);
     private static final NodeIdentifier DESTINATION_TYPE = new NodeIdentifier(DestinationType.QNAME);
+    private static final InstanceIdentifier TABLES_II = InstanceIdentifier.create(BgpRib.class)
+            .child(Rib.class).child(LocRib.class).child(Tables.class);
     private static final NodeIdentifier ROUTES = new NodeIdentifier(Routes.QNAME);
     private static final ApplyRoute DELETE_ROUTE = new DeleteRoute();
     private final NodeIdentifier routesContainerIdentifier;
@@ -102,19 +103,22 @@ public abstract class AbstractRIBSupport<
     private final QName routeKeyQname;
     private final NodeIdentifier prefixTypeNid;
     private final NodeIdentifier rdNid;
-    private final BindingNormalizedNodeSerializer mappingService;
+    protected final BindingNormalizedNodeSerializer mappingService;
+    protected final YangInstanceIdentifier routeDefaultYii;
 
     /**
      * Default constructor. Requires the QName of the container augmented under the routes choice
      * node in instantiations of the rib grouping. It is assumed that this container is defined by
      * the same model which populates it with route grouping instantiation, and by extension with
      * the route attributes container.
+     *
+     * @param mappingService   Serialization service
      * @param cazeClass        Binding class of the AFI/SAFI-specific case statement, must not be null
      * @param containerClass   Binding class of the container in routes choice, must not be null.
      * @param listClass        Binding class of the route list, nust not be null;
      * @param afiClass         address Family Class
      * @param safiClass        SubsequentAddressFamily
-     * @param destinationQname destination Qname
+     * @param destContainerQname destination Container Qname
      */
     protected AbstractRIBSupport(
             final BindingNormalizedNodeSerializer mappingService,
@@ -123,36 +127,43 @@ public abstract class AbstractRIBSupport<
             final Class<R> listClass,
             final Class<? extends AddressFamily> afiClass,
             final Class<? extends SubsequentAddressFamily> safiClass,
-            final QName destinationQname) {
-        final QName qname = BindingReflections.findQName(containerClass).intern();
-        this.routesContainerIdentifier = new NodeIdentifier(qname);
-        this.routeAttributesIdentifier = new NodeIdentifier(QName.create(qname,
-                Attributes.QNAME.getLocalName().intern()));
+            final QName destContainerQname) {
+        final QNameModule module = BindingReflections.getQNameModule(cazeClass);
+        this.routesContainerIdentifier
+                = new NodeIdentifier(BindingReflections.findQName(containerClass).withModule(module));
+        this.routeAttributesIdentifier = new NodeIdentifier(Attributes.QNAME.withModule(module));
         this.cazeClass = requireNonNull(cazeClass);
         this.mappingService = requireNonNull(mappingService);
         this.containerClass = requireNonNull(containerClass);
         this.listClass = requireNonNull(listClass);
-        this.routeQname = QName.create(qname, BindingReflections.findQName(listClass).intern().getLocalName());
+        this.routeQname = BindingReflections.findQName(listClass).withModule(module);
         this.routesListIdentifier = new NodeIdentifier(this.routeQname);
-
         final TablesKey tk = new TablesKey(afiClass, safiClass);
-        //FIXME Use Route Iid instead of Tables.
-        final InstanceIdentifier<Tables> routeIID = InstanceIdentifier.create(BgpRib.class)
-                .child(Rib.class, new RibKey(requireNonNull(new RibId("rib"))))
-                .child(LocRib.class)
-                .child(Tables.class, tk);
+        //FIXME Use Route Case IId instead of Tables IId.
         this.emptyRoutes = (ChoiceNode) ((MapEntryNode) this.mappingService
-                .toNormalizedNode(routeIID, new TablesBuilder().setKey(tk)
+                .toNormalizedNode(TABLES_II, new TablesBuilder().setKey(tk)
                         .setRoutes(emptyRoutesCase()).build()).getValue())
                 .getChild(new NodeIdentifier(BindingReflections.findQName(Routes.class))).get();
         this.afiClass = afiClass;
         this.safiClass = safiClass;
-        this.destinationNid = new NodeIdentifier(destinationQname);
+        this.destinationNid = new NodeIdentifier(destContainerQname);
         this.pathIdQname = QName.create(routeQName(), "path-id").intern();
         this.pathIdNid = new NodeIdentifier(this.pathIdQname);
         this.routeKeyQname = QName.create(routeQName(), ROUTE_KEY).intern();
-        this.prefixTypeNid = NodeIdentifier.create(QName.create(destinationQname, "prefix").intern());
-        this.rdNid = NodeIdentifier.create(QName.create(destinationQname, "route-distinguisher").intern());
+        this.prefixTypeNid = NodeIdentifier.create(QName.create(destContainerQname, "prefix").intern());
+        this.rdNid = NodeIdentifier.create(QName.create(destContainerQname, "route-distinguisher").intern());
+        this.routeDefaultYii =
+                YangInstanceIdentifier.builder()
+                        .node(BgpRib.QNAME)
+                        .node(Rib.QNAME)
+                        .node(Rib.QNAME)
+                        .node(LocRib.QNAME)
+                        .node(Tables.QNAME)
+                        .node(Tables.QNAME)
+                        .node(Routes.QNAME)
+                        .node(BindingReflections.findQName(containerClass).withModule(module))
+                        .node(this.routeQname)
+                        .node(this.routeQname).build();
     }
 
     @Override
index c44e012fffe84ead62e08b7359f2ab01b8a397b2..548f90bb434ea5ed67f819a1231f04c94196d560 100644 (file)
@@ -157,7 +157,7 @@ public abstract class AbstractRIBSupportTest<R extends Route> extends AbstractCo
 
     private InstanceIdentifier<DataObject> routesIId() {
         final InstanceIdentifier<Tables> tables = tablesIId();
-        return tables.child((Class) this.abstractRIBSupport.routesContainerClass());
+        return tables.child(this.abstractRIBSupport.routesContainerClass());
     }
 
     protected final YangInstanceIdentifier getTablePath() {
@@ -183,8 +183,8 @@ public abstract class AbstractRIBSupportTest<R extends Route> extends AbstractCo
     }
 
     private QName getRouteListQname() {
-        return QName.create(BindingReflections.findQName(this.abstractRIBSupport.routesContainerClass()),
-                BindingReflections.findQName(this.abstractRIBSupport.routesListClass()).intern().getLocalName());
+        return BindingReflections.findQName(this.abstractRIBSupport.routesListClass())
+                .withModule(BindingReflections.getQNameModule(this.abstractRIBSupport.routesCaseClass()));
     }
 
     protected final NodeIdentifierWithPredicates createRouteNIWP(final DataObject routes) {
index 31d26e7d6e4f3d08d568894e507bc349ffa559dd..67e382b6c78189af6b45d7dbbf96bdb32443bd8b 100644 (file)
             <classifier>features</classifier>
             <type>xml</type>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>odl-bgpcep-bgp-mvpn</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>odl-bgpcep-bgp-evpn</artifactId>
index 200f611b7fecd2938a343a33fae9036c84f7e9c4..b6a43170af7ee21ce13f8675e4647fab7e131b90 100644 (file)
             <type>xml</type>
             <classifier>features</classifier>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>odl-bgpcep-bgp-mvpn</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>odl-bgpcep-bgp-evpn</artifactId>