BUG-4827: BGP Add Path Flowspec ribSupport 66/37666/11
authorClaudio D. Gasparini <cgaspari@cisco.com>
Fri, 15 Apr 2016 10:51:51 +0000 (12:51 +0200)
committerMilos Fabian <milfabia@cisco.com>
Thu, 28 Apr 2016 12:00:56 +0000 (12:00 +0000)
Implement support for add path on flowspec extension

Change-Id: Id7f94ed1719bfa0326d7c652586d594e94e4141a
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/AbstractFlowspecNlriParser.java
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/AbstractFlowspecRIBSupport.java
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/SimpleFlowspecIpv4NlriParser.java
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/SimpleFlowspecIpv6NlriParser.java
bgp/flowspec/src/main/yang/bgp-flowspec.yang
bgp/flowspec/src/test/java/org/opendaylight/protocol/bgp/flowspec/SimpleFlowspecIpv4NlriParserTest.java
bgp/flowspec/src/test/java/org/opendaylight/protocol/bgp/flowspec/SimpleFlowspecIpv6NlriParserTest.java

index 1db6478b7fe6331583574218180ac5365136d896..1115eaabc0b361fe1bdaa43d4cae565ee79692fa 100644 (file)
@@ -18,12 +18,18 @@ import io.netty.buffer.Unpooled;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.protocol.bgp.flowspec.handlers.BitmaskOperandParser;
 import org.opendaylight.protocol.bgp.flowspec.handlers.NumericOneByteOperandParser;
 import org.opendaylight.protocol.bgp.flowspec.handlers.NumericTwoByteOperandParser;
 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.PathIdUtil;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Dscp;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Fragment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.Flowspec;
@@ -67,6 +73,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlagsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.DestinationPrefixCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.SourcePrefixCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
@@ -75,6 +82,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.rev130919.update.attributes.MpUnreachNlriBuilder;
 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.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.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -149,9 +158,9 @@ public abstract class AbstractFlowspecNlriParser implements NlriParser, NlriSeri
 
     protected abstract void stringSpecificFSNlriType(final FlowspecType value, final StringBuilder buffer);
 
-    abstract DestinationType createWithdrawnDestinationType(final List<Flowspec> dst);
+    abstract DestinationType createWithdrawnDestinationType(final List<Flowspec> dst, @Nullable final PathId pathId);
 
-    abstract DestinationType createAdvertizedRoutesDestinationType(final List<Flowspec> dst);
+    abstract DestinationType createAdvertizedRoutesDestinationType(final List<Flowspec> dst, @Nullable final PathId pathId);
 
     @Override
     public final void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
@@ -165,31 +174,24 @@ public abstract class AbstractFlowspecNlriParser implements NlriParser, NlriSeri
 
     @Override
     public final void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
-        if (!nlri.isReadable()) {
-            return;
-        }
-        final List<Flowspec> dst = parseNlri(nlri);
-
-        builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(createWithdrawnDestinationType(dst)).build());
+        parseNlri(nlri, builder, null);
     }
 
     @Override
     public final void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
-        if (!nlri.isReadable()) {
-            return;
-        }
-        final List<Flowspec> dst = parseNlri(nlri);
-        builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(createAdvertizedRoutesDestinationType(dst)).build());
+        parseNlri(nlri, builder, null);
     }
 
     /**
      * Serializes Flowspec NLRI to ByteBuf.
-     *
-     * @param flows flowspec NLRI to be serialized
+     *  @param flows flowspec NLRI to be serialized
+     * @param pathId
      * @param buffer where flowspec NLRI will be serialized
      */
-    public final void serializeNlri(final List<Flowspec> flows, final ByteBuf buffer) {
+    public final void serializeNlri(final List<Flowspec> flows, final PathId pathId, final ByteBuf buffer) {
         final ByteBuf nlriByteBuf = Unpooled.buffer();
+        PathIdUtil.writePathId(pathId, buffer);
+
         for (final Flowspec flow : flows) {
             this.flowspecTypeRegistry.serializeFlowspecType(flow.getFlowspecType(), nlriByteBuf);
         }
@@ -551,4 +553,34 @@ public abstract class AbstractFlowspecNlriParser implements NlriParser, NlriSeri
         return fss;
     }
 
+
+    @Override
+    public void parseNlri(@Nonnull final ByteBuf nlri, @Nonnull final MpReachNlriBuilder builder, @Nullable final PeerSpecificParserConstraint constraint) throws BGPParsingException {
+        if (!nlri.isReadable()) {
+            return;
+        }
+        final PathId pathId = readPathId(nlri, builder.getAfi(), builder.getSafi(), constraint);
+        final List<Flowspec> dst = parseNlri(nlri);
+        builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder()
+            .setDestinationType(createAdvertizedRoutesDestinationType(dst, pathId)).build());
+    }
+
+    private PathId readPathId(final ByteBuf nlri, final Class<? extends AddressFamily> afi, final Class<? extends SubsequentAddressFamily> safi,
+        final PeerSpecificParserConstraint constraint) {
+        if (MultiPathSupportUtil.isTableTypeSupported(constraint, new BgpTableTypeImpl(afi, safi))) {
+            return PathIdUtil.readPathId(nlri);
+        }
+        return null;
+    }
+
+
+    @Override
+    public void parseNlri(@Nonnull final ByteBuf nlri, @Nonnull final MpUnreachNlriBuilder builder, @Nullable final PeerSpecificParserConstraint constraint) throws BGPParsingException {
+        if (!nlri.isReadable()) {
+            return;
+        }
+        final PathId pathId = readPathId(nlri, builder.getAfi(), builder.getSafi(), constraint);
+        final List<Flowspec> dst = parseNlri(nlri);
+        builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(createWithdrawnDestinationType(dst, pathId)).build());
+    }
 }
index 6b5b547c6b0a711f149ee6849010fa0c6b337b4c..4a19e81fe260494d1de050dba9cc08cdc2bf7882 100644 (file)
@@ -11,11 +11,14 @@ import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import java.util.Collection;
+import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupport;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.FlowspecSubsequentAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.ipv6.routes.flowspec.ipv6.routes.FlowspecRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
@@ -36,12 +39,15 @@ 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.NormalizedNode;
 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;
 
 public abstract class AbstractFlowspecRIBSupport extends AbstractRIBSupport {
+    private static final QName PATHID_QNAME = QName.create(FlowspecRoute.QNAME, "path-id").intern();
+    private static final NodeIdentifier PATH_ID_NII = new NodeIdentifier(PATHID_QNAME);
 
     protected abstract static class ApplyRoute {
         abstract void apply(DOMDataWriteTransaction tx, YangInstanceIdentifier base, NodeIdentifierWithPredicates routeKey, DataContainerNode<?> route, final ContainerNode attributes);
@@ -131,9 +137,11 @@ public abstract class AbstractFlowspecRIBSupport extends AbstractRIBSupport {
         mb.setSafi(FlowspecSubsequentAddressFamily.class);
         mb.setCNextHop(hop);
 
-        mb.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
-            getParser().createAdvertizedRoutesDestinationType(
-                getParser().extractFlowspec(Iterables.getOnlyElement(routes)))).build());
+        final MapEntryNode routesCont = Iterables.getOnlyElement(routes);
+        final PathId pathId = PathIdUtil.buildPathId(routesCont, PATH_ID_NII);
+
+        mb.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(getParser().createAdvertizedRoutesDestinationType(
+            getParser().extractFlowspec(routesCont), pathId)).build());
         return mb.build();
     }
 
@@ -143,9 +151,22 @@ public abstract class AbstractFlowspecRIBSupport extends AbstractRIBSupport {
         mb.setAfi(getAfiClass());
         mb.setSafi(FlowspecSubsequentAddressFamily.class);
 
-        mb.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
-            getParser().createWithdrawnDestinationType(
-                getParser().extractFlowspec(Iterables.getOnlyElement(routes)))).build());
+        final MapEntryNode routesCont = Iterables.getOnlyElement(routes);
+        final PathId pathId = PathIdUtil.buildPathId(routesCont, PATH_ID_NII);
+
+        mb.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(getParser().createWithdrawnDestinationType(
+            getParser().extractFlowspec(Iterables.getOnlyElement(routes)), pathId)).build());
         return mb.build();
     }
+
+    @Nullable
+    @Override
+    public PathArgument getRouteIdAddPath(final long pathId, final PathArgument routeId) {
+        return PathIdUtil.createNiiKey(pathId, routeId, FlowspecRoute.QNAME, PATHID_QNAME, ROUTE_KEY);
+    }
+
+    @Override
+    public Long extractPathId(final NormalizedNode<?, ?> data) {
+        return PathIdUtil.extractPathId(data, PATH_ID_NII);
+    }
 }
index 370983e7af73c6687f0a61beba0d42853029a30c..4be3216087e2034a53b1564d32ec0c2b836ea044 100644 (file)
@@ -26,7 +26,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.SourcePrefixCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.protocol.ip._case.ProtocolIps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.protocol.ip._case.ProtocolIpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.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.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.DestinationType;
@@ -49,17 +51,17 @@ public final class SimpleFlowspecIpv4NlriParser extends AbstractFlowspecNlriPars
     }
 
     @Override
-    DestinationType createWithdrawnDestinationType(final List<Flowspec> dst) {
+    DestinationType createWithdrawnDestinationType(final List<Flowspec> dst, final PathId pathId) {
         return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCaseBuilder().setDestinationFlowspec(
             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder().setFlowspec(
-                dst).build()).build();
+                dst).setPathId(pathId).build()).build();
     }
 
     @Override
-    DestinationType createAdvertizedRoutesDestinationType(final List<Flowspec> dst) {
+    DestinationType createAdvertizedRoutesDestinationType(final List<Flowspec> dst, final PathId pathId) {
         return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCaseBuilder()
             .setDestinationFlowspec(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder()
-                .setFlowspec(dst).build()).build();
+                .setFlowspec(dst).setPathId(pathId).build()).build();
     }
 
     @Override
@@ -69,8 +71,9 @@ public final class SimpleFlowspecIpv4NlriParser extends AbstractFlowspecNlriPars
         }
         final AdvertizedRoutes routes = (pathAttributes.getMpReachNlri()).getAdvertizedRoutes();
         if (routes != null && routes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase) {
-            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase flowspecCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase) routes.getDestinationType();
-            serializeNlri(flowspecCase.getDestinationFlowspec().getFlowspec(), byteAggregator);
+            final DestinationFlowspec destFlowspec= ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update
+                .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase) routes.getDestinationType()).getDestinationFlowspec();
+            serializeNlri(destFlowspec.getFlowspec(), destFlowspec.getPathId(), byteAggregator);
         }
     }
 
@@ -127,8 +130,9 @@ public final class SimpleFlowspecIpv4NlriParser extends AbstractFlowspecNlriPars
         }
         final MpUnreachNlri mpUnreachNlri = pathAttributes.getMpUnreachNlri();
         if (mpUnreachNlri.getWithdrawnRoutes() != null && mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationFlowspecCase) {
-            final DestinationFlowspecCase flowspecCase = (DestinationFlowspecCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
-            serializeNlri(flowspecCase.getDestinationFlowspec().getFlowspec(), byteAggregator);
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.
+                routes.destination.type.destination.flowspec._case.DestinationFlowspec flowspecCase = ((DestinationFlowspecCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType()).getDestinationFlowspec();
+            serializeNlri(flowspecCase.getFlowspec(), flowspecCase.getPathId(), byteAggregator);
         }
     }
 }
index fc83549e4914b0d0f914debc1409853282491dec..a79ac934d4cbee95e2ee3f7472c297f04076e4c8 100644 (file)
@@ -29,7 +29,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.flow.label._case.FlowLabelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.next.header._case.NextHeaders;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.next.header._case.NextHeadersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec.ipv6._case.DestinationFlowspec;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecIpv6Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.DestinationType;
@@ -52,17 +54,17 @@ public final class SimpleFlowspecIpv6NlriParser extends AbstractFlowspecNlriPars
     }
 
     @Override
-    DestinationType createWithdrawnDestinationType(final List<Flowspec> dst) {
+    DestinationType createWithdrawnDestinationType(final List<Flowspec> dst, final PathId pathId) {
         return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecIpv6CaseBuilder().setDestinationFlowspec(
             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec.ipv6._case.DestinationFlowspecBuilder().setFlowspec(
-                dst).build()).build();
+                dst).setPathId(pathId).build()).build();
     }
 
     @Override
-    DestinationType createAdvertizedRoutesDestinationType(final List<Flowspec> dst) {
+    DestinationType createAdvertizedRoutesDestinationType(final List<Flowspec> dst, final PathId pathId) {
         return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecIpv6CaseBuilder()
             .setDestinationFlowspec(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec.ipv6._case.DestinationFlowspecBuilder()
-                .setFlowspec(dst).build()).build();
+                .setFlowspec(dst).setPathId(pathId).build()).build();
     }
 
     @Override
@@ -72,8 +74,9 @@ public final class SimpleFlowspecIpv6NlriParser extends AbstractFlowspecNlriPars
         }
         final AdvertizedRoutes routes = (pathAttributes.getMpReachNlri()).getAdvertizedRoutes();
         if (routes != null && routes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecIpv6Case) {
-            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecIpv6Case flowspecCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecIpv6Case) routes.getDestinationType();
-            serializeNlri(flowspecCase.getDestinationFlowspec().getFlowspec(), byteAggregator);
+            final DestinationFlowspec destFlowspec = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri
+                    .advertized.routes.destination.type.DestinationFlowspecIpv6Case) routes.getDestinationType()).getDestinationFlowspec();
+            serializeNlri(destFlowspec.getFlowspec(), destFlowspec.getPathId(), byteAggregator);
         }
     }
 
@@ -170,8 +173,10 @@ public final class SimpleFlowspecIpv6NlriParser extends AbstractFlowspecNlriPars
         }
         final MpUnreachNlri mpUnreachNlri = pathAttributes.getMpUnreachNlri();
         if (mpUnreachNlri.getWithdrawnRoutes() != null && mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationFlowspecIpv6Case) {
-            final DestinationFlowspecIpv6Case flowspecCase = (DestinationFlowspecIpv6Case) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
-            serializeNlri(flowspecCase.getDestinationFlowspec().getFlowspec(), byteAggregator);
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.
+                routes.destination.type.destination.flowspec.ipv6._case.DestinationFlowspec flowspecCase = ((DestinationFlowspecIpv6Case) mpUnreachNlri.getWithdrawnRoutes().getDestinationType()
+            ).getDestinationFlowspec();
+            serializeNlri(flowspecCase.getFlowspec(), flowspecCase.getPathId(), byteAggregator);
         }
     }
 }
index 15057aabe7f0a232b51834cad53a6c057d8e0f68..18ec7c18857757f4ced8cf537863c591ebb1d7a4 100644 (file)
@@ -208,6 +208,7 @@ module bgp-flowspec {
                 }
             }
         }
+        uses bgp-msg:path-id-grouping;
     }
 
     grouping flowspec-destination-ipv4 {
@@ -395,7 +396,7 @@ module bgp-flowspec {
                         API contract of this model.";
                     type string;
                 }
-                key "route-key";
+                key "route-key path-id";
 
                 uses flowspec-destination-ipv4;
 
@@ -442,7 +443,7 @@ module bgp-flowspec {
                         API contract of this model.";
                     type string;
                 }
-                key "route-key";
+                key "route-key path-id";
 
                 uses flowspec-destination-ipv6;
 
index 35f4e7d74bfaf6a3373724ef82aab798b6efd083..d4f2af84e015ccc385c633e0bf37264787ebc1e8 100644 (file)
@@ -16,34 +16,37 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractNumericOperandParser;
 import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractOperandParser;
 import org.opendaylight.protocol.bgp.flowspec.handlers.BitmaskOperandParser;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupport;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.util.ByteArray;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.BitmaskOperand;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Dscp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.FlowspecSubsequentAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Fragment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.Flowspec;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.FlowspecBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.DestinationPortCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.FlowspecType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.DestinationPortCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.DscpCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.DscpCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.FragmentCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.FragmentCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.IcmpCodeCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.IcmpCodeCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.IcmpTypeCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.IcmpTypeCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.PacketLengthCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.PacketLengthCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.PortCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.PortCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.SourcePortCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.SourcePortCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.TcpFlagsCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.TcpFlagsCaseBuilder;
@@ -67,7 +70,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.tcp.flags._case.TcpFlagsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.DestinationPrefixCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.DestinationPrefixCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.ProtocolIpCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.ProtocolIpCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.SourcePrefixCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv4.flowspec.flowspec.type.SourcePrefixCaseBuilder;
@@ -77,6 +79,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flow
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1Builder;
@@ -94,26 +97,65 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContaine
 
 public class SimpleFlowspecIpv4NlriParserTest {
 
-    private static final byte[] REACHED_NLRI = new byte[] { 0x21,
+    static final PathId PATH_ID = new PathId(1L);
+    @Mock
+    private PeerSpecificParserConstraint constraint;
+    @Mock
+    private MultiPathSupport muliPathSupport;
+
+    private static final byte[] REACHED_NLRI = new byte[] {
+        0x21,
+        01, 0x20, 0x0a, 00, 01, 00,
+        02, 0x20, 01, 02, 03, 04,
+        03, (byte) 0x81, 06,
+        04, 03, (byte) 0x89, 0x45, (byte) 0x8b, (byte) 0x91, 0x1f, (byte) 0x90,
+        05, 0x12, 0x0f, (byte) 0xf9, (byte) 0x81, (byte) 0xb3,
+        06, (byte) 0x91, 0x1f, (byte) 0x90
+    };
+
+    private static final byte[] REACHED_NLRI_ADD_PATH = new byte[] {
+        0x0, 0x0, 0x0, 0x1,
+        0x21,
         01, 0x20, 0x0a, 00, 01, 00,
         02, 0x20, 01, 02, 03, 04,
         03, (byte) 0x81, 06,
         04, 03, (byte) 0x89, 0x45, (byte) 0x8b, (byte) 0x91, 0x1f, (byte) 0x90,
         05, 0x12, 0x0f, (byte) 0xf9, (byte) 0x81, (byte) 0xb3,
-        06, (byte) 0x91, 0x1f, (byte) 0x90 };
+        06, (byte) 0x91, 0x1f, (byte) 0x90
+    };
+
+    private static final byte[] UNREACHED_NLRI = new byte[] {
+        0x1B,
+        07, 4, 2, (byte) 0x84, 3,
+        0x08, 4, 04, (byte) 0x80, 05,
+        0x09, 0x12, 04, 01, (byte) 0x91, 0x56, (byte) 0xb1,
+        0x0a, (byte) 0x94, (byte) 0xde, (byte) 0xad,
+        0x0b, (byte) 0x82, 0x2a,
+        0x0c, (byte) 0x81, (byte) 0x0e
+    };
 
-    private static final byte[] UNREACHED_NLRI = new byte[] { 0x1B,
+    private static final byte[] UNREACHED_NLRI_ADD_PATH = new byte[] {
+        0x0, 0x0, 0x0, 0x1,
+        0x1B,
         07, 4, 2, (byte) 0x84, 3,
         0x08, 4, 04, (byte) 0x80, 05,
         0x09, 0x12, 04, 01, (byte) 0x91, 0x56, (byte) 0xb1,
         0x0a, (byte) 0x94, (byte) 0xde, (byte) 0xad,
         0x0b, (byte) 0x82, 0x2a,
-        0x0c, (byte) 0x81, (byte) 0x0e};
+        0x0c, (byte) 0x81, (byte) 0x0e
+    };
 
     private final SimpleFlowspecExtensionProviderContext flowspecContext = new SimpleFlowspecExtensionProviderContext();
     private final FlowspecActivator fsa = new FlowspecActivator(flowspecContext);
     private final SimpleFlowspecIpv4NlriParser FS_PARSER = new SimpleFlowspecIpv4NlriParser(flowspecContext.getFlowspecIpv4TypeRegistry());
 
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Mockito.doReturn(Optional.of(this.muliPathSupport)).when(constraint).getPeerConstraint(Mockito.any());
+        Mockito.doReturn(true).when(this.muliPathSupport).isTableTypeSupported(Mockito.any());
+    }
+
     @Test
     public void testParseMpReachNlri() throws BGPParsingException {
         final List<Flowspec> fs = new ArrayList<>();
@@ -127,38 +169,43 @@ public class SimpleFlowspecIpv4NlriParserTest {
         builder.setFlowspecType(sourcePrefix);
         fs.add(builder.build());
 
-        final List<ProtocolIps> protocols = Lists.newArrayList(new ProtocolIpsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue((short)6).build());
-        final ProtocolIpCase prots = new ProtocolIpCaseBuilder().setProtocolIps(protocols).build();
+        final FlowspecType prots = createProts();
         builder.setFlowspecType(prots);
         fs.add(builder.build());
 
-        final List<Ports> ports = Lists.newArrayList(new PortsBuilder().setOp(new NumericOperand(false, false, true, true, false)).setValue(137).build(),
-            new PortsBuilder().setOp(new NumericOperand(true, false, true, false, true)).setValue(139).build(),
-            new PortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(8080).build());
-        final PortCase ps = new PortCaseBuilder().setPorts(ports).build();
+        final PortCase ps = createPorts();
         builder.setFlowspecType(ps);
         fs.add(builder.build());
 
-        final List<DestinationPorts> destports = Lists.newArrayList(new DestinationPortsBuilder().setOp(new NumericOperand(false, false, false, true, false)).setValue(4089).build(),
-            new DestinationPortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(179).build());
-        final DestinationPortCase dps = new DestinationPortCaseBuilder().setDestinationPorts(destports).build();
+        final FlowspecType dps = createDps();
         builder.setFlowspecType(dps);
         fs.add(builder.build());
 
-        final List<SourcePorts> sports = Lists.newArrayList(new SourcePortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(8080).build());
-        final SourcePortCase sps = new SourcePortCaseBuilder().setSourcePorts(sports).build();
+        final FlowspecType sps = createSps();
         builder.setFlowspecType(sps);
         fs.add(builder.build());
 
-        mp.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(new DestinationFlowspecCaseBuilder().setDestinationFlowspec(new DestinationFlowspecBuilder().setFlowspec(fs).build()).build()).build());
+        mp.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(new DestinationFlowspecCaseBuilder().setDestinationFlowspec(new
+            DestinationFlowspecBuilder().setFlowspec(fs).build()).build()).build());
 
         final SimpleFlowspecIpv4NlriParser parser = new SimpleFlowspecIpv4NlriParser(flowspecContext.getFlowspecIpv4TypeRegistry());
 
         final MpReachNlriBuilder result = new MpReachNlriBuilder();
         result.setAfi(Ipv4AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
         parser.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI), result);
 
         final List<Flowspec> flows = ((DestinationFlowspecCase) (result.getAdvertizedRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
+        testFlows(flows, destinationPrefix, sourcePrefix, prots, prots, ps, dps, sps);
+
+        final ByteBuf buffer = Unpooled.buffer();
+        parser.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes1.class, new Attributes1Builder().setMpReachNlri(mp.setAfi(Ipv4AddressFamily.class).build()).build()).build(), buffer);
+        assertArrayEquals(REACHED_NLRI, ByteArray.readAllBytes(buffer));
+
+        assertEquals("all packets to 10.0.1.0/32 AND from 1.2.3.4/32 AND where IP protocol equals to 6 AND where port is greater than or equals to 137 and is less than or equals to 139 or equals to 8080 AND where destination port is greater than 4089 or equals to 179 AND where source port equals to 8080 ", FS_PARSER.stringNlri(flows));
+    }
+
+    private void testFlows(final List<Flowspec> flows, final DestinationPrefixCase destinationPrefix, final SourcePrefixCase sourcePrefix, final FlowspecType prots, final FlowspecType flowspecType, final PortCase ps, final FlowspecType dps, final FlowspecType sps) {
         assertEquals(6, flows.size());
         assertEquals(destinationPrefix, flows.get(0).getFlowspecType());
         assertEquals(sourcePrefix, flows.get(1).getFlowspecType());
@@ -166,14 +213,81 @@ public class SimpleFlowspecIpv4NlriParserTest {
         assertEquals(ps, flows.get(3).getFlowspecType());
         assertEquals(dps, flows.get(4).getFlowspecType());
         assertEquals(sps, flows.get(5).getFlowspecType());
+    }
+
+    private FlowspecType createSps() {
+        final List<SourcePorts> sports = Lists.newArrayList(new SourcePortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(8080).build());
+        return new SourcePortCaseBuilder().setSourcePorts(sports).build();
+    }
+
+    private FlowspecType createProts() {
+        final List<ProtocolIps> protocols = Lists.newArrayList(new ProtocolIpsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue((short)6).build());
+        return new ProtocolIpCaseBuilder().setProtocolIps(protocols).build();
+    }
+
+    private FlowspecType createDps() {
+        final List<DestinationPorts> destports = Lists.newArrayList(new DestinationPortsBuilder().setOp(new NumericOperand(false, false, false, true, false)).setValue(4089).build(),
+            new DestinationPortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(179).build());
+        return new DestinationPortCaseBuilder().setDestinationPorts(destports).build();
+    }
+
+    @Test
+    public void testParseMpReachNlriConstraint() throws BGPParsingException {
+        final List<Flowspec> fs = new ArrayList<>();
+        final MpReachNlriBuilder mp = new MpReachNlriBuilder();
+
+        final FlowspecBuilder builder = new FlowspecBuilder();
+        final DestinationPrefixCase destinationPrefix = new DestinationPrefixCaseBuilder().setDestinationPrefix(new Ipv4Prefix("10.0.1.0/32")).build();
+        builder.setFlowspecType(destinationPrefix);
+        fs.add(builder.build());
+        final SourcePrefixCase sourcePrefix = new SourcePrefixCaseBuilder().setSourcePrefix(new Ipv4Prefix("1.2.3.4/32")).build();
+        builder.setFlowspecType(sourcePrefix);
+        fs.add(builder.build());
+
+        final FlowspecType prots = createProts();
+        builder.setFlowspecType(prots);
+        fs.add(builder.build());
+
+        final PortCase ps = createPorts();
+        builder.setFlowspecType(ps);
+        fs.add(builder.build());
+
+        final FlowspecType dps = createDps();
+        builder.setFlowspecType(dps);
+        fs.add(builder.build());
+
+        final FlowspecType sps = createSps();
+        builder.setFlowspecType(sps);
+        fs.add(builder.build());
+
+        mp.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(new DestinationFlowspecCaseBuilder().setDestinationFlowspec(new
+            DestinationFlowspecBuilder().setPathId(PATH_ID).setFlowspec(fs).build()).build()).build());
+
+        final SimpleFlowspecIpv4NlriParser parser = new SimpleFlowspecIpv4NlriParser(flowspecContext.getFlowspecIpv4TypeRegistry());
+
+        final MpReachNlriBuilder result = new MpReachNlriBuilder();
+        result.setAfi(Ipv4AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
+        parser.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI_ADD_PATH), result, this.constraint);
+
+        final List<Flowspec> flows = ((DestinationFlowspecCase) (result.getAdvertizedRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
+        testFlows(flows, destinationPrefix, sourcePrefix, prots, prots, ps,dps, sps);
 
         final ByteBuf buffer = Unpooled.buffer();
         parser.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes1.class, new Attributes1Builder().setMpReachNlri(mp.setAfi(Ipv4AddressFamily.class).build()).build()).build(), buffer);
-        assertArrayEquals(REACHED_NLRI, ByteArray.readAllBytes(buffer));
+        assertArrayEquals(REACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
 
         assertEquals("all packets to 10.0.1.0/32 AND from 1.2.3.4/32 AND where IP protocol equals to 6 AND where port is greater than or equals to 137 and is less than or equals to 139 or equals to 8080 AND where destination port is greater than 4089 or equals to 179 AND where source port equals to 8080 ", FS_PARSER.stringNlri(flows));
     }
 
+    private PortCase createPorts() {
+        final List<Ports> ports = Lists.newArrayList(new PortsBuilder().setOp(new NumericOperand(false, false, true, true, false)).setValue(137).build(),
+            new PortsBuilder().setOp(new NumericOperand(true, false, true, false, true)).setValue(139).build(),
+            new PortsBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(8080).build());
+
+        return new PortCaseBuilder().setPorts(ports).build();
+    }
+
     @Test
     public void testParseMpUnreachNlri() throws BGPParsingException {
         final List<Flowspec> fs = new ArrayList<>();
@@ -181,50 +295,92 @@ public class SimpleFlowspecIpv4NlriParserTest {
 
         final FlowspecBuilder builder = new FlowspecBuilder();
 
-        final List<Types> types = Lists.newArrayList(new TypesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue((short) 2).build(),
-            new TypesBuilder().setOp(new NumericOperand(false, true, false, false, true)).setValue((short) 3).build());
-        final IcmpTypeCase icmpType = new IcmpTypeCaseBuilder().setTypes(types).build();
+        final FlowspecType icmpType = createIcmpType();
         builder.setFlowspecType(icmpType);
         fs.add(builder.build());
 
-        final List<Codes> codes = Lists.newArrayList(new CodesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue((short) 4).build(),
-            new CodesBuilder().setOp(new NumericOperand(false, true, false, false, false)).setValue((short) 5).build());
-        final IcmpCodeCase icmpCode = new IcmpCodeCaseBuilder().setCodes(codes).build();
+        final FlowspecType icmpCode = createIcmpCode();
         builder.setFlowspecType(icmpCode);
         fs.add(builder.build());
 
-        final List<TcpFlags> flags = Lists.newArrayList(new TcpFlagsBuilder().setOp(new BitmaskOperand(false, false, false, true)).setValue(1025).build(),
-            new TcpFlagsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(22193).build());
-        final TcpFlagsCase tcp = new TcpFlagsCaseBuilder().setTcpFlags(flags).build();
+        final TcpFlagsCase tcp = createTcp();
         builder.setFlowspecType(tcp);
         fs.add(builder.build());
 
-        final List<PacketLengths> packets = Lists.newArrayList(new PacketLengthsBuilder().setOp(new NumericOperand(false, true, false, false, true)).setValue(57005).build());
-        final PacketLengthCase packet = new PacketLengthCaseBuilder().setPacketLengths(packets).build();
+        final PacketLengthCase packet = createPackets();
         builder.setFlowspecType(packet);
         fs.add(builder.build());
 
-        final List<Dscps> dscps = Lists.newArrayList(new DscpsBuilder().setOp(new NumericOperand(false, true, false, true, false)).setValue(new Dscp((short) 42)).build());
-        final DscpCase dscp = new DscpCaseBuilder().setDscps(dscps).build();
+        final FlowspecType dscp = createDscp();
         builder.setFlowspecType(dscp);
         fs.add(builder.build());
 
-        final List<Fragments> fragments = Lists.newArrayList(new FragmentsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(new Fragment(false, true, true, true)).build());
-        final FragmentCase fragment = new FragmentCaseBuilder().setFragments(fragments).build();
+        final FlowspecType fragment = createFragment();
         builder.setFlowspecType(fragment);
         fs.add(builder.build());
 
         mp.setAfi(Ipv4AddressFamily.class).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCaseBuilder().setDestinationFlowspec(
-                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder().setFlowspec(fs).build()).build()).build());
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder()
+                    .setFlowspec(fs).build()).build()).build());
 
         final SimpleFlowspecIpv4NlriParser parser = new SimpleFlowspecIpv4NlriParser(flowspecContext.getFlowspecIpv4TypeRegistry());
 
         final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder();
         result.setAfi(Ipv4AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
         parser.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI), result);
 
         final List<Flowspec> flows = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCase) (result.getWithdrawnRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
+        checkUnreachFlows(flows, icmpType, icmpCode, tcp, packet, dscp, fragment);
+
+        final ByteBuf buffer = Unpooled.buffer();
+        parser.serializeNlri(flows, null, buffer);
+        assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer));
+
+        parser.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(mp.build()).build()).build(), buffer);
+        assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer));
+
+        assertEquals("all packets where ICMP type is less than 2 or is less than 3 AND where ICMP code is less than 4 or 5 AND where TCP flags is not 1025 or does match 22193 AND where packet length is less than 57005 AND where DSCP is greater than 42 AND where fragment does match 'IS FIRST' 'IS LAST' 'IS A' ", FS_PARSER.stringNlri(flows));
+
+    }
+
+    private FlowspecType createFragment() {
+        final List<Fragments> fragments = Lists.newArrayList(new FragmentsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(new Fragment(false, true, true, true)).build());
+        return new FragmentCaseBuilder().setFragments(fragments).build();
+    }
+
+    private FlowspecType createDscp() {
+        final List<Dscps> dscps = Lists.newArrayList(new DscpsBuilder().setOp(new NumericOperand(false, true, false, true, false)).setValue(new Dscp((short) 42)).build());
+        return new DscpCaseBuilder().setDscps(dscps).build();
+    }
+
+    private PacketLengthCase createPackets() {
+        final List<PacketLengths> packets = Lists.newArrayList(new PacketLengthsBuilder().setOp(new NumericOperand(false, true, false, false, true))
+            .setValue(57005).build());
+        return new PacketLengthCaseBuilder().setPacketLengths(packets).build();
+    }
+
+    private TcpFlagsCase createTcp() {
+        final List<TcpFlags> flags = Lists.newArrayList(new TcpFlagsBuilder().setOp(new BitmaskOperand(false, false, false, true)).setValue(1025).build(),
+            new TcpFlagsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(22193).build());
+        return new TcpFlagsCaseBuilder().setTcpFlags(flags).build();
+    }
+
+    private FlowspecType createIcmpCode() {
+        final List<Codes> codes = Lists.newArrayList(new CodesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue((short) 4).build(),
+            new CodesBuilder().setOp(new NumericOperand(false, true, false, false, false)).setValue((short) 5).build());
+        return new IcmpCodeCaseBuilder().setCodes(codes).build();
+    }
+
+    private FlowspecType createIcmpType() {
+        final List<Types> types = Lists.newArrayList(new TypesBuilder().setOp(new NumericOperand(false, false, false, false, true)).setValue((short) 2).build(),
+            new TypesBuilder().setOp(new NumericOperand(false, true, false, false, true)).setValue((short) 3).build());
+        return new IcmpTypeCaseBuilder().setTypes(types).build();
+    }
+
+    private void checkUnreachFlows(final List<Flowspec> flows, final FlowspecType icmpType, final FlowspecType icmpCode, final TcpFlagsCase tcp,
+        final PacketLengthCase packet, final FlowspecType dscp, final FlowspecType fragment) {
         assertEquals(6, flows.size());
         assertEquals(icmpType, flows.get(0).getFlowspecType());
         assertEquals(icmpCode, flows.get(1).getFlowspecType());
@@ -232,13 +388,61 @@ public class SimpleFlowspecIpv4NlriParserTest {
         assertEquals(packet, flows.get(3).getFlowspecType());
         assertEquals(dscp, flows.get(4).getFlowspecType());
         assertEquals(fragment, flows.get(5).getFlowspecType());
+    }
+
+    @Test
+    public void testParseMpUnreachNlriConstraint() throws BGPParsingException {
+        final List<Flowspec> fs = new ArrayList<>();
+        final MpUnreachNlriBuilder mp = new MpUnreachNlriBuilder();
+
+        final FlowspecBuilder builder = new FlowspecBuilder();
+
+        final FlowspecType icmpType = createIcmpType();
+        builder.setFlowspecType(icmpType);
+        fs.add(builder.build());
+
+        final FlowspecType icmpCode = createIcmpCode();
+        builder.setFlowspecType(icmpCode);
+        fs.add(builder.build());
+
+        final TcpFlagsCase tcp = createTcp();
+        builder.setFlowspecType(tcp);
+        fs.add(builder.build());
+
+        final PacketLengthCase packet = createPackets();
+        builder.setFlowspecType(packet);
+        fs.add(builder.build());
+
+        final FlowspecType dscp = createDscp();
+        builder.setFlowspecType(dscp);
+        fs.add(builder.build());
+
+        final FlowspecType fragment = createFragment();
+        builder.setFlowspecType(fragment);
+        fs.add(builder.build());
+
+        mp.setAfi(Ipv4AddressFamily.class).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCaseBuilder().setDestinationFlowspec(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder()
+                    .setPathId(PATH_ID).setFlowspec(fs).build()).build()).build());
+
+        final SimpleFlowspecIpv4NlriParser parser = new SimpleFlowspecIpv4NlriParser(flowspecContext.getFlowspecIpv4TypeRegistry());
+
+        final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder();
+        result.setAfi(Ipv4AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
+        parser.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI_ADD_PATH), result, this.constraint);
+
+        final List<Flowspec> flows = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCase) (result.getWithdrawnRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
+        checkUnreachFlows(flows, icmpType, icmpCode, tcp, packet, dscp, fragment);
+
 
         final ByteBuf buffer = Unpooled.buffer();
-        parser.serializeNlri(flows, buffer);
-        assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer));
+        parser.serializeNlri(flows, PATH_ID, buffer);
+        assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
 
         parser.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(mp.build()).build()).build(), buffer);
-        assertArrayEquals(UNREACHED_NLRI, ByteArray.readAllBytes(buffer));
+        assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
 
         assertEquals("all packets where ICMP type is less than 2 or is less than 3 AND where ICMP code is less than 4 or 5 AND where TCP flags is not 1025 or does match 22193 AND where packet length is less than 57005 AND where DSCP is greater than 42 AND where fragment does match 'IS FIRST' 'IS LAST' 'IS A' ", FS_PARSER.stringNlri(flows));
 
index 586e0d5f7d4a35a9d4ec85120c247b479cea7de4..93757b0945af48508fe9271981d44d95ceba7544 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.protocol.bgp.flowspec;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.opendaylight.protocol.bgp.flowspec.SimpleFlowspecIpv4NlriParserTest.PATH_ID;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -16,25 +17,33 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractNumericOperandParser;
 import org.opendaylight.protocol.bgp.flowspec.handlers.AbstractOperandParser;
 import org.opendaylight.protocol.bgp.flowspec.handlers.BitmaskOperandParser;
 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupport;
+import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
 import org.opendaylight.protocol.util.ByteArray;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.BitmaskOperand;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.FlowspecSubsequentAddressFamily;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.Fragment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.NumericOperand;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.Flowspec;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.FlowspecBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.FlowspecType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.FragmentCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.FragmentCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.fragment._case.Fragments;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.flowspec.flowspec.type.fragment._case.FragmentsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.DestinationIpv6PrefixCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.DestinationIpv6PrefixCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.FlowLabelCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.FlowLabelCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.NextHeaderCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.flowspec.destination.ipv6.flowspec.flowspec.type.NextHeaderCaseBuilder;
@@ -64,19 +73,46 @@ import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 
 public class SimpleFlowspecIpv6NlriParserTest {
-
+    @Mock
+    private PeerSpecificParserConstraint constraint;
+    @Mock
+    private MultiPathSupport muliPathSupport;
     private final SimpleFlowspecExtensionProviderContext flowspecContext = new SimpleFlowspecExtensionProviderContext();
     private final FlowspecActivator fsa = new FlowspecActivator(flowspecContext);
     private final SimpleFlowspecIpv6NlriParser FS_PARSER = new SimpleFlowspecIpv6NlriParser(flowspecContext.getFlowspecIpv6TypeRegistry());
 
-    private static final byte[] REACHED_NLRI = new byte[] {  0x13,
+    private static final byte[] REACHED_NLRI = new byte[] {
+        0x13,
+        1, 0x28, 0, 1, 2, 3, 4, 5,
+        2, 0x28, 0, 1, 2, 3, 4, 6,
+        03, (byte) 0x81, 06 };
+
+    private static final byte[] REACHED_NLRI_ADD_PATH = new byte[] {
+        0x0, 0x0, 0x0, 0x1,
+        0x13,
         1, 0x28, 0, 1, 2, 3, 4, 5,
         2, 0x28, 0, 1, 2, 3, 4, 6,
         03, (byte) 0x81, 06 };
 
-    private static final byte[] UNREACHED_NLRI = new byte[] { 0x0c,
+    private static final byte[] UNREACHED_NLRI = new byte[] {
+        0x0c,
         0x0c, (byte) 0x81, 0x0e,
-        0x0d, (byte) 0x21, 1, 0, 0, 6, (byte) 0x91, 1, 2 };
+        0x0d, (byte) 0x21, 1, 0, 0, 6, (byte) 0x91, 1, 2
+    };
+
+    private static final byte[] UNREACHED_NLRI_ADD_PATH = new byte[] {
+        0x0, 0x0, 0x0, 0x1,
+        0x0c,
+        0x0c, (byte) 0x81, 0x0e,
+        0x0d, (byte) 0x21, 1, 0, 0, 6, (byte) 0x91, 1, 2
+    };
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        Mockito.doReturn(Optional.of(this.muliPathSupport)).when(constraint).getPeerConstraint(Mockito.any());
+        Mockito.doReturn(true).when(this.muliPathSupport).isTableTypeSupported(Mockito.any());
+    }
 
     @Test
     public void testParseMpReachNlri() throws BGPParsingException {
@@ -98,10 +134,12 @@ public class SimpleFlowspecIpv6NlriParserTest {
         fs.add(builder.build());
 
 
-        mp.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(new DestinationFlowspecIpv6CaseBuilder().setDestinationFlowspec(new DestinationFlowspecBuilder().setFlowspec(fs).build()).build()).build());
+        mp.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(new DestinationFlowspecIpv6CaseBuilder().setDestinationFlowspec(
+            new DestinationFlowspecBuilder().setFlowspec(fs).build()).build()).build());
 
         final MpReachNlriBuilder result = new MpReachNlriBuilder();
         result.setAfi(Ipv6AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
         FS_PARSER.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI), result);
 
         final List<Flowspec> flows = ((DestinationFlowspecIpv6Case) (result.getAdvertizedRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
@@ -117,6 +155,47 @@ public class SimpleFlowspecIpv6NlriParserTest {
         assertEquals("all packets to 102:304:500::/40 AND from 102:304:600::/40 AND where next header equals to 6 ", FS_PARSER.stringNlri(flows));
     }
 
+    @Test
+    public void testParseMpReachNlriConstraint() throws BGPParsingException {
+        final List<Flowspec> fs = new ArrayList<>();
+        final MpReachNlriBuilder mp = new MpReachNlriBuilder();
+
+        final FlowspecBuilder builder = new FlowspecBuilder();
+        final DestinationIpv6PrefixCase destinationPrefix = new DestinationIpv6PrefixCaseBuilder().setDestinationPrefix(new Ipv6Prefix("102:304:500::/40")).build();
+        builder.setFlowspecType(destinationPrefix);
+        fs.add(builder.build());
+
+        final SourceIpv6PrefixCase sourcePrefix = new SourceIpv6PrefixCaseBuilder().setSourcePrefix(new Ipv6Prefix("102:304:600::/40")).build();
+        builder.setFlowspecType(sourcePrefix);
+        fs.add(builder.build());
+
+        final List<NextHeaders> nextheaders = Lists.newArrayList(new NextHeadersBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue((short) 6).build());
+        final NextHeaderCase headersCase = new NextHeaderCaseBuilder().setNextHeaders(nextheaders).build();
+        builder.setFlowspecType(headersCase);
+        fs.add(builder.build());
+
+
+        mp.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(new DestinationFlowspecIpv6CaseBuilder().setDestinationFlowspec(
+            new DestinationFlowspecBuilder().setPathId(PATH_ID).setFlowspec(fs).build()).build()).build());
+
+        final MpReachNlriBuilder result = new MpReachNlriBuilder();
+        result.setAfi(Ipv6AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
+        FS_PARSER.parseNlri(Unpooled.wrappedBuffer(REACHED_NLRI_ADD_PATH), result, this.constraint);
+
+        final List<Flowspec> flows = ((DestinationFlowspecIpv6Case) (result.getAdvertizedRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
+        assertEquals(3, flows.size());
+        assertEquals(destinationPrefix, flows.get(0).getFlowspecType());
+        assertEquals(sourcePrefix, flows.get(1).getFlowspecType());
+        assertEquals(headersCase, flows.get(2).getFlowspecType());
+
+        final ByteBuf buffer = Unpooled.buffer();
+        FS_PARSER.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes1.class, new Attributes1Builder().setMpReachNlri(mp.setAfi(Ipv6AddressFamily.class).build()).build()).build(), buffer);
+        assertArrayEquals(REACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
+
+        assertEquals("all packets to 102:304:500::/40 AND from 102:304:600::/40 AND where next header equals to 6 ", FS_PARSER.stringNlri(flows));
+    }
+
     @Test
     public void testParseMpUnreachNlri() throws BGPParsingException {
         final List<Flowspec> fs = new ArrayList<>();
@@ -124,15 +203,11 @@ public class SimpleFlowspecIpv6NlriParserTest {
 
         final FlowspecBuilder builder = new FlowspecBuilder();
 
-        final List<Fragments> fragments = Lists.newArrayList(new FragmentsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(new Fragment(false, true, true, true)).build());
-        final FragmentCase fragment = new FragmentCaseBuilder().setFragments(fragments).build();
+        final FragmentCase fragment = createFragment();
         builder.setFlowspecType(fragment);
         fs.add(builder.build());
 
-        final List<FlowLabel> labels = Lists.newArrayList();
-        labels.add(new FlowLabelBuilder().setOp(new NumericOperand(false, false, true, false, false)).setValue(new Long(16777222L)).build());
-        labels.add(new FlowLabelBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(new Long(258L)).build());
-        final FlowLabelCase label = new FlowLabelCaseBuilder().setFlowLabel(labels).build();
+        final FlowspecType label = createLabel();
         builder.setFlowspecType(label);
         fs.add(builder.build());
 
@@ -142,6 +217,7 @@ public class SimpleFlowspecIpv6NlriParserTest {
 
         final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder();
         result.setAfi(Ipv6AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
         FS_PARSER.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI), result);
 
         final List<Flowspec> flows = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecIpv6Case) (result.getWithdrawnRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
@@ -157,6 +233,55 @@ public class SimpleFlowspecIpv6NlriParserTest {
         assertEquals("all packets where fragment does match 'IS FIRST' 'IS LAST' 'IS A' AND where flow label equals to 16777222 or equals to 258 ", FS_PARSER.stringNlri(flows));
     }
 
+    private FragmentCase createFragment() {
+        final List<Fragments> fragments = Lists.newArrayList(new FragmentsBuilder().setOp(new BitmaskOperand(false, true, true, false)).setValue(new Fragment(false, true, true, true)).build());
+        return new FragmentCaseBuilder().setFragments(fragments).build();
+    }
+
+    private FlowspecType createLabel() {
+        final List<FlowLabel> labels = Lists.newArrayList();
+        labels.add(new FlowLabelBuilder().setOp(new NumericOperand(false, false, true, false, false)).setValue(new Long(16777222L)).build());
+        labels.add(new FlowLabelBuilder().setOp(new NumericOperand(false, true, true, false, false)).setValue(new Long(258L)).build());
+        return new FlowLabelCaseBuilder().setFlowLabel(labels).build();
+    }
+
+    @Test
+    public void testParseMpUnreachNlriConstraint() throws BGPParsingException {
+        final List<Flowspec> fs = new ArrayList<>();
+        final MpUnreachNlriBuilder mp = new MpUnreachNlriBuilder();
+
+        final FlowspecBuilder builder = new FlowspecBuilder();
+        final FragmentCase fragment = createFragment();
+
+        builder.setFlowspecType(fragment);
+        fs.add(builder.build());
+
+        final FlowspecType label =  createLabel();
+        builder.setFlowspecType(label);
+        fs.add(builder.build());
+
+        mp.setAfi(Ipv6AddressFamily.class).setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
+            new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecIpv6CaseBuilder().setDestinationFlowspec(
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec.ipv6._case.DestinationFlowspecBuilder().setPathId(PATH_ID).setFlowspec(fs).build()).build()).build());
+
+        final MpUnreachNlriBuilder result = new MpUnreachNlriBuilder();
+        result.setAfi(Ipv6AddressFamily.class);
+        result.setSafi(FlowspecSubsequentAddressFamily.class);
+        FS_PARSER.parseNlri(Unpooled.wrappedBuffer(UNREACHED_NLRI_ADD_PATH), result, this.constraint);
+
+        final List<Flowspec> flows = ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150807.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecIpv6Case) (result.getWithdrawnRoutes().getDestinationType())).getDestinationFlowspec().getFlowspec();
+        assertEquals(2, flows.size());
+        assertEquals(fragment, flows.get(0).getFlowspecType());
+        assertEquals(label, flows.get(1).getFlowspecType());
+
+        final ByteBuf buffer = Unpooled.buffer();
+        FS_PARSER.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(mp.build()).build()).build(), buffer);
+
+        assertArrayEquals(UNREACHED_NLRI_ADD_PATH, ByteArray.readAllBytes(buffer));
+
+        assertEquals("all packets where fragment does match 'IS FIRST' 'IS LAST' 'IS A' AND where flow label equals to 16777222 or equals to 258 ", FS_PARSER.stringNlri(flows));
+    }
+
     @Test
     public void testExtractFlowspecFragments() {
         final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry = Builders.mapEntryBuilder();