BUG-2571 : implemented (partially) conversion of Flowspec 01/18801/3
authorDana Kutenicsova <dkutenic@cisco.com>
Wed, 22 Apr 2015 08:08:19 +0000 (10:08 +0200)
committerDana Kutenicsova <dkutenic@cisco.com>
Wed, 22 Apr 2015 12:06:38 +0000 (14:06 +0200)
from BI to BA form

We need this to advertise Flowspec back to peers. The
advertising is done in BA form.

Change-Id: Ifc5e0e1bffaaf756afdfd44944281e3b9a36250a
Signed-off-by: Dana Kutenicsova <dkutenic@cisco.com>
bgp/flowspec/src/main/java/org/opendaylight/protocol/bgp/flowspec/FSNlriParser.java
bgp/flowspec/src/test/java/org/opendaylight/protocol/bgp/flowspec/FSNlriParserTest.java

index 8e871f69dacec1649ce8becb4ad46497a307a6ac..d9e6a23123baa724266e6080c96ebc9f70fcea85 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.protocol.bgp.flowspec;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.primitives.UnsignedBytes;
 import com.google.common.primitives.UnsignedInts;
@@ -23,6 +24,7 @@ import org.opendaylight.protocol.util.ByteArray;
 import org.opendaylight.protocol.util.ByteBufWriteUtil;
 import org.opendaylight.protocol.util.Ipv4Util;
 import org.opendaylight.protocol.util.Values;
+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.rev150114.BitmaskOperand;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.ComponentType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.NumericOneByteValue;
@@ -88,6 +90,11 @@ 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.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.slf4j.Logger;
@@ -96,6 +103,23 @@ import org.slf4j.LoggerFactory;
 public class FSNlriParser implements NlriParser, NlriSerializer {
     private static final Logger LOG = LoggerFactory.getLogger(FSNlriParser.class);
 
+    private static final NodeIdentifier FLOWSPEC_TYPE_NID = new NodeIdentifier(FlowspecType.QNAME);
+    @VisibleForTesting
+    static final NodeIdentifier COMPONENT_TYPE_NID = new NodeIdentifier(QName.cachedReference(QName.create(Flowspec.QNAME, "component-type")));
+    @VisibleForTesting
+    static final NodeIdentifier DEST_PREFIX_NID = new NodeIdentifier(QName.cachedReference(QName.create(DestinationPrefixCase.QNAME, "destination-prefix")));
+    private static final NodeIdentifier SOURCE_PREFIX_NID = new NodeIdentifier(QName.cachedReference(QName.create(SourcePrefixCase.QNAME, "source-prefix")));
+    private static final NodeIdentifier PROTOCOL_IP_NID = new NodeIdentifier(ProtocolIps.QNAME);
+    private static final NodeIdentifier PORTS_NID = new NodeIdentifier(Ports.QNAME);
+    private static final NodeIdentifier DEST_PORT_NID = new NodeIdentifier(DestinationPorts.QNAME);
+    private static final NodeIdentifier SOURCE_PORT_NID = new NodeIdentifier(SourcePorts.QNAME);
+    private static final NodeIdentifier ICMP_TYPE_NID = new NodeIdentifier(Types.QNAME);
+    private static final NodeIdentifier ICMP_CODE_NID = new NodeIdentifier(Codes.QNAME);
+    private static final NodeIdentifier TCP_FLAGS_NID = new NodeIdentifier(TcpFlags.QNAME);
+    private static final NodeIdentifier PACKET_LENGTHS_NID = new NodeIdentifier(PacketLengths.QNAME);
+    private static final NodeIdentifier DSCP_NID = new NodeIdentifier(Dscps.QNAME);
+    private static final NodeIdentifier FRAGMENT_NID = new NodeIdentifier(Fragments.QNAME);
+
     private static final int NLRI_LENGTH = 1;
     private static final int NLRI_LENGTH_EXTENDED = 2;
     /**
@@ -589,7 +613,81 @@ public class FSNlriParser implements NlriParser, NlriSerializer {
     }
 
     public static Flowspec extractFlowspec(final MapEntryNode route) {
-        // FIXME: BUG-2571 : finish this
-        return new FlowspecBuilder().build();
+        final FlowspecBuilder fs = new FlowspecBuilder();
+        final Optional<DataContainerChild<? extends PathArgument, ?>> compType = route.getChild(COMPONENT_TYPE_NID);
+        if (compType.isPresent()) {
+            fs.setComponentType(componentTypeValue((String) compType.get().getValue()));
+        }
+        final ChoiceNode fsType = (ChoiceNode) route.getChild(FLOWSPEC_TYPE_NID).get();
+        if (fsType.getChild(DEST_PREFIX_NID).isPresent()) {
+            fs.setFlowspecType(new DestinationPrefixCaseBuilder().setDestinationPrefix(
+                    new Ipv4Prefix((String) fsType.getChild(DEST_PREFIX_NID).get().getValue())).build());
+        } else if (fsType.getChild(SOURCE_PREFIX_NID).isPresent()) {
+            fs.setFlowspecType(new SourcePrefixCaseBuilder().setSourcePrefix(new Ipv4Prefix((String) fsType.getChild(SOURCE_PREFIX_NID).get().getValue()))
+                    .build());
+        } else if (fsType.getChild(PROTOCOL_IP_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new ProtocolIpCaseBuilder().build());
+        } else if (fsType.getChild(PORTS_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new PortCaseBuilder().build());
+        } else if (fsType.getChild(DEST_PORT_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new DestinationPortCaseBuilder().build());
+        } else if (fsType.getChild(SOURCE_PORT_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new SourcePortCaseBuilder().build());
+        } else if (fsType.getChild(ICMP_TYPE_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new IcmpTypeCaseBuilder().build());
+        } else if (fsType.getChild(ICMP_CODE_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new IcmpCodeCaseBuilder().build());
+        } else if (fsType.getChild(TCP_FLAGS_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new TcpFlagsCaseBuilder().build());
+        } else if (fsType.getChild(PACKET_LENGTHS_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new PacketLengthCaseBuilder().build());
+        } else if (fsType.getChild(DSCP_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new DscpCaseBuilder().build());
+        } else if (fsType.getChild(FRAGMENT_NID).isPresent()) {
+            // FIXME: BUG-3044
+            fs.setFlowspecType(new FragmentCaseBuilder().build());
+        }
+        return fs.build();
+    }
+
+    // FIXME: use codec
+    private static ComponentType componentTypeValue(final String compType) {
+        switch (compType) {
+        case "destination-prefix":
+            return ComponentType.DestinationPrefix;
+        case "source-prefix":
+            return ComponentType.SourcePrefix;
+        case "protocol-ip":
+            return ComponentType.ProtocolIp;
+        case "port":
+            return ComponentType.Port;
+        case "destination-port":
+            return ComponentType.DestinationPort;
+        case "source-port":
+            return ComponentType.SourcePort;
+        case "icmp-type":
+            return ComponentType.IcmpType;
+        case "icmp-code":
+            return ComponentType.IcmpCode;
+        case "tcp-flags":
+            return ComponentType.TcpFlags;
+        case "packet-length":
+            return ComponentType.PacketLength;
+        case "dscp":
+            return ComponentType.Dscp;
+        case "fragment":
+            return ComponentType.Fragment;
+        default:
+            return null;
+        }
     }
 }
index 117fa8f91f117a63be07a89299b9e022ef6f594b..b25020444baa160479b7ad037c3099bf192d8ddd 100644 (file)
@@ -26,6 +26,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.rev150114.NumericOperand;
 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.destination.FlowspecBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.FlowspecType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPortCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPortCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.flowspec.flowspec.type.DestinationPrefixCase;
@@ -82,6 +83,11 @@ 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.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 
 public class FSNlriParserTest {
 
@@ -241,4 +247,17 @@ public class FSNlriParserTest {
         parser.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes2.class, new Attributes2Builder().setMpUnreachNlri(mp.build()).build()).build(), buffer);
         assertArrayEquals(unnlri, ByteArray.readAllBytes(buffer));
     }
+
+    @Test
+    public void testExtractFlowspec() {
+        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> entry = Builders.mapEntryBuilder();
+        entry.withNodeIdentifier(new NodeIdentifierWithPredicates(Flowspec.QNAME, Flowspec.QNAME, entry));
+        entry.withChild(Builders.leafBuilder().withNodeIdentifier(FSNlriParser.COMPONENT_TYPE_NID).withValue("destination-prefix").build());
+        entry.withChild(Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(FlowspecType.QNAME))
+            .withChild(Builders.leafBuilder().withNodeIdentifier(FSNlriParser.DEST_PREFIX_NID).withValue("127.0.0.5/32").build()).build());
+        final FlowspecBuilder expected = new FlowspecBuilder();
+        expected.setComponentType(ComponentType.DestinationPrefix);
+        expected.setFlowspecType(new DestinationPrefixCaseBuilder().setDestinationPrefix(new Ipv4Prefix("127.0.0.5/32")).build());
+        assertEquals(expected.build(), FSNlriParser.extractFlowspec(entry.build()));
+    }
 }