Fix MVPN
[bgpcep.git] / bgp / rib-spi / src / main / java / org / opendaylight / protocol / bgp / rib / spi / AbstractRIBSupport.java
index 46c7d7802f70bdc857248f0ec86735f6bc98a5b0..fcf04912cad70f8d5e561d3bd0b1dd22bf984a06 100644 (file)
@@ -13,39 +13,46 @@ import com.google.common.annotations.Beta;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Optional;
-import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.Update;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.UpdateBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.Attributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.AttributesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.Attributes1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.Attributes1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.Attributes2;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.Attributes2Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.destination.DestinationType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.MpReachNlri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.MpReachNlriBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.MpUnreachNlri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.MpUnreachNlriBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.mp.reach.nlri.AdvertizedRoutes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev171207.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.Route;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.Tables;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.TablesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.rib.tables.Routes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+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.message.rev180329.UpdateBuilder;
+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.message.rev180329.path.attributes.AttributesBuilder;
+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.Attributes1Builder;
+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.Attributes2Builder;
+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.MpReachNlri;
+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.MpUnreachNlri;
+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.rib.rev180329.BgpRib;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
+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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisherBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.SubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.CNextHop;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 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;
@@ -64,27 +71,40 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Beta
-public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
-        implements RIBSupport<R, N> {
+public abstract class AbstractRIBSupport<
+        C extends Routes & DataObject,
+        S extends DataObject,
+        R extends Route,
+        I extends Identifier>
+        implements RIBSupport<C, S, R, I> {
     public static final String ROUTE_KEY = "route-key";
     private static final Logger LOG = LoggerFactory.getLogger(AbstractRIBSupport.class);
     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> 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;
     private final NodeIdentifier routesListIdentifier;
     private final NodeIdentifier routeAttributesIdentifier;
-    private final Class<? extends Routes> cazeClass;
-    private final Class<? extends DataObject> containerClass;
-    private final Class<? extends Route> listClass;
+    private final Class<C> cazeClass;
+    private final Class<S> containerClass;
+    private final Class<R> listClass;
     private final ApplyRoute putRoute = new PutRoute();
     private final ChoiceNode emptyRoutes;
     private final QName routeQname;
     private final Class<? extends AddressFamily> afiClass;
     private final Class<? extends SubsequentAddressFamily> safiClass;
     private final NodeIdentifier destinationNid;
+    private final QName pathIdQname;
+    private final NodeIdentifier pathIdNid;
+    private final QName routeKeyQname;
+    private final NodeIdentifier prefixTypeNid;
+    private final NodeIdentifier rdNid;
+    protected final BindingNormalizedNodeSerializer mappingService;
+    protected final YangInstanceIdentifier routeDefaultYii;
 
     /**
      * Default constructor. Requires the QName of the container augmented under the routes choice
@@ -92,49 +112,72 @@ public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
      * 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 Class<? extends Routes> cazeClass,
-            final Class<? extends DataObject> containerClass,
-            final Class<? extends Route> listClass, final Class<? extends AddressFamily> afiClass,
+            final BindingNormalizedNodeSerializer mappingService,
+            final Class<C> cazeClass,
+            final Class<S> containerClass,
+            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);
-        this.emptyRoutes = Builders.choiceBuilder().withNodeIdentifier(ROUTES)
-                .addChild(Builders.containerBuilder()
-                .withNodeIdentifier(routesContainerIdentifier())
-                .withChild(ImmutableNodes.mapNodeBuilder(this.routeQname).build()).build()).build();
+        final TablesKey tk = new TablesKey(afiClass, safiClass);
+        //FIXME Use Route Case IId instead of Tables IId.
+        this.emptyRoutes = (ChoiceNode) ((MapEntryNode) this.mappingService
+                .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(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
-    public final Class<? extends Routes> routesCaseClass() {
+    public final Class<C> routesCaseClass() {
         return this.cazeClass;
     }
 
     @Override
-    public final Class<? extends DataObject> routesContainerClass() {
+    public final Class<S> routesContainerClass() {
         return this.containerClass;
     }
 
     @Override
-    public final Class<? extends Route> routesListClass() {
+    public final Class<R> routesListClass() {
         return this.listClass;
     }
 
@@ -147,17 +190,19 @@ public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
         return this.routeQname;
     }
 
+    protected final NodeIdentifier prefixNid() {
+        return this.prefixTypeNid;
+    }
+
     protected final NodeIdentifier routeNid() {
         return this.routesListIdentifier;
     }
 
-    @Nonnull
     @Override
     public final Class<? extends AddressFamily> getAfi() {
         return this.afiClass;
     }
 
-    @Nonnull
     @Override
     public final Class<? extends SubsequentAddressFamily> getSafi() {
         return this.safiClass;
@@ -194,11 +239,9 @@ public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
         return mb.build();
     }
 
-    @Nonnull
-    protected abstract DestinationType buildDestination(@Nonnull Collection<MapEntryNode> routes);
+    protected abstract DestinationType buildDestination(Collection<MapEntryNode> routes);
 
-    @Nonnull
-    protected abstract DestinationType buildWithdrawnDestination(@Nonnull Collection<MapEntryNode> routes);
+    protected abstract DestinationType buildWithdrawnDestination(Collection<MapEntryNode> routes);
 
     /**
      * Return the {@link NodeIdentifier} of the AFI/SAFI-specific container under
@@ -319,7 +362,7 @@ public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
 
     @Override
     public final InstanceIdentifier<R> createRouteIdentifier(
-            final KeyedInstanceIdentifier<Tables, TablesKey> tableIId, final N key) {
+            final KeyedInstanceIdentifier<Tables, TablesKey> tableIId, final I key) {
         return tableIId.child((Class) routesContainerClass()).child(routesListClass(), key);
     }
 
@@ -335,7 +378,6 @@ public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
         putRoutes(tx, tablePath, nlri, attributes, ROUTES);
     }
 
-    @Nonnull
     @Override
     public final Update buildUpdate(final Collection<MapEntryNode> advertised, final Collection<MapEntryNode> withdrawn,
             final Attributes attr) {
@@ -420,4 +462,28 @@ public abstract class AbstractRIBSupport<R extends Route, N extends Identifier>
             tx.put(LogicalDatastoreType.OPERATIONAL, base.node(routeKey), b.build());
         }
     }
+
+    protected final NodeIdentifier routePathIdNid() {
+        return this.pathIdNid;
+    }
+
+    protected final QName pathIdQName() {
+        return this.pathIdQname;
+    }
+
+    protected final QName routeKeyQName() {
+        return this.routeKeyQname;
+    }
+
+    protected final String extractPrefix(final DataContainerNode<? extends PathArgument> route) {
+        return (String) route.getChild(prefixTypeNid).get().getValue();
+    }
+
+    protected final RouteDistinguisher extractRouteDistinguisher(
+            final DataContainerNode<? extends PathArgument> route) {
+        if (route.getChild(this.rdNid).isPresent()) {
+            return RouteDistinguisherBuilder.getDefaultInstance((String) route.getChild(this.rdNid).get().getValue());
+        }
+        return null;
+    }
 }