BUG-2571 : initial cut on Flowspec RIB Support 41/18541/2
authorDana Kutenicsova <dkutenic@cisco.com>
Fri, 17 Apr 2015 13:08:37 +0000 (15:08 +0200)
committerDana Kutenicsova <dkutenic@cisco.com>
Fri, 17 Apr 2015 13:16:36 +0000 (15:16 +0200)
Change-Id: I83697949e1b203f09a12584ead80bd5ed1b7638c
Signed-off-by: Dana Kutenicsova <dkutenic@cisco.com>
bgp/flowspec/pom.xml
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/FSNlriParser.java
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/FlowspecRIBSupport.java [new file with mode: 0644]

index 6f7519c9f6477434ec11c1494f0bdb72035048ff..123f1aeaa65ad5f0e9a4396d40b049d69f1025f5 100644 (file)
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>bgp-rib-api</artifactId>
+        </dependency>
+         <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>bgp-rib-spi</artifactId>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>ietf-inet-types</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-api</artifactId>
+        </dependency>
 
          <dependency>
             <groupId>io.netty</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.opendaylight.controller</groupId>
-            <artifactId>sal-common-api</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
index 785ae99e6330bf1b671698685848aa6c456dd746..99e922d64bdd127f350b6b1496bfbd954beca374 100644 (file)
@@ -88,6 +88,7 @@ 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.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -580,4 +581,9 @@ public class FSNlriParser implements NlriParser, NlriSerializer {
         bs.set(LAST_FRAGMENT, fragment.isLast());
         return bs.toByte();
     }
+
+    public static String stringNlri(final UnkeyedListEntryNode linkstate) {
+        // FIXME: BUG-2571 : create human-readable route key, e.g : "all packets to 10.0.1/24 from 192/8 and port {range [137, 139] or 8080}"
+        return "";
+    }
 }
diff --git a/bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/FlowspecRIBSupport.java b/bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/FlowspecRIBSupport.java
new file mode 100644 (file)
index 0000000..3d30be2
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.flowspec;
+
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupport;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.FlowspecRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.bgp.rib.rib.loc.rib.tables.routes.FlowspecRoutesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.Flowspec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.routes.flowspec.routes.FlowspecRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec._case.DestinationFlowspec;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
+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.ChoiceNode;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class FlowspecRIBSupport extends AbstractRIBSupport {
+
+    private static abstract class ApplyRoute {
+        abstract void apply(DOMDataWriteTransaction tx, YangInstanceIdentifier base, NodeIdentifierWithPredicates routeKey, DataContainerNode<?> route, final ContainerNode attributes);
+    }
+
+    private static final class DeleteRoute extends ApplyRoute {
+        @Override
+        void apply(final DOMDataWriteTransaction tx, final YangInstanceIdentifier base, final NodeIdentifierWithPredicates routeKey, final DataContainerNode<?> route, final ContainerNode attributes) {
+            tx.delete(LogicalDatastoreType.OPERATIONAL, base.node(routeKey));
+        }
+    }
+
+    private final class PutRoute extends ApplyRoute {
+        @Override
+        void apply(final DOMDataWriteTransaction tx, final YangInstanceIdentifier base, final NodeIdentifierWithPredicates routeKey,
+            final DataContainerNode<?> route, final ContainerNode attributes) {
+            final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> b = ImmutableNodes.mapEntryBuilder();
+            b.withNodeIdentifier(routeKey);
+
+            // FIXME: All route children, there should be a utility somewhere to do this
+            for (final DataContainerChild<? extends PathArgument, ?> child : route.getValue()) {
+                b.withChild(child);
+            }
+            // Add attributes
+            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> cb = Builders.containerBuilder(attributes);
+            cb.withNodeIdentifier(routeAttributesIdentifier());
+            b.withChild(cb.build());
+            tx.put(LogicalDatastoreType.OPERATIONAL, base.node(routeKey), b.build());
+        }
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(FlowspecRIBSupport.class);
+
+    private static final QName ROUTE_KEY = QName.cachedReference(QName.create(FlowspecRoute.QNAME, "route-key"));
+    private static final FlowspecRIBSupport SINGLETON = new FlowspecRIBSupport();
+    private static final ApplyRoute DELETE_ROUTE = new DeleteRoute();
+
+    private final ChoiceNode emptyRoutes = Builders.choiceBuilder()
+        .withNodeIdentifier(new NodeIdentifier(Routes.QNAME))
+        .addChild(Builders.containerBuilder()
+            .withNodeIdentifier(new NodeIdentifier(FlowspecRoutes.QNAME))
+            .addChild(ImmutableNodes.mapNodeBuilder(FlowspecRoute.QNAME).build()).build()).build();
+    private final NodeIdentifier destination = new NodeIdentifier(DestinationFlowspec.QNAME);
+    private final NodeIdentifier route = new NodeIdentifier(FlowspecRoute.QNAME);
+    private final NodeIdentifier nlriRoutesList = new NodeIdentifier(Flowspec.QNAME);
+    private final ApplyRoute putRoute = new PutRoute();
+
+    private FlowspecRIBSupport() {
+        super(FlowspecRoutesCase.class, FlowspecRoutes.class, FlowspecRoute.class);
+    }
+
+    static FlowspecRIBSupport getInstance() {
+        return SINGLETON;
+    }
+
+    @Override
+    public ChoiceNode emptyRoutes() {
+        return this.emptyRoutes;
+    }
+
+    @Override
+    public ImmutableCollection<Class<? extends DataObject>> cacheableAttributeObjects() {
+        return ImmutableSet.of();
+    }
+
+    @Override
+    public ImmutableCollection<Class<? extends DataObject>> cacheableNlriObjects() {
+        return ImmutableSet.of();
+    }
+
+    @Override
+    public boolean isComplexRoute() {
+        return true;
+    }
+
+    @Override
+    protected NodeIdentifier destinationContainerIdentifier() {
+        return this.destination;
+    }
+
+    private void processDestination(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
+        final ContainerNode destination, final ContainerNode attributes, final ApplyRoute function) {
+        if (destination != null) {
+            final Optional<DataContainerChild<? extends PathArgument, ?>> maybeRoutes = destination.getChild(this.nlriRoutesList);
+            if (maybeRoutes.isPresent()) {
+                final DataContainerChild<? extends PathArgument, ?> routes = maybeRoutes.get();
+                if (routes instanceof UnkeyedListNode) {
+                    final YangInstanceIdentifier base = tablePath.node(ROUTES).node(routesContainerIdentifier()).node(this.route);
+                    for (final UnkeyedListEntryNode e : ((UnkeyedListNode)routes).getValue()) {
+                        final NodeIdentifierWithPredicates routeKey = new NodeIdentifierWithPredicates(FlowspecRoute.QNAME, ROUTE_KEY, FSNlriParser.stringNlri(e));
+                        function.apply(tx, base, routeKey,  e, attributes);
+                    }
+                } else {
+                    LOG.warn("Routes {} are not a map", routes);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void deleteDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
+        final ContainerNode destination) {
+        processDestination(tx, tablePath, destination, null, DELETE_ROUTE);
+    }
+
+    @Override
+    protected void putDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
+        final ContainerNode destination, final ContainerNode attributes) {
+        processDestination(tx, tablePath, destination, attributes, this.putRoute);
+    }
+}