Fix For NETVIRT-1389 57/74457/12
authorananth <ananth.y@hcl.com>
Wed, 25 Jul 2018 13:50:54 +0000 (22:50 +0900)
committerSam Hague <shague@redhat.com>
Mon, 17 Sep 2018 00:14:48 +0000 (00:14 +0000)
Implemented flows for TCP and UDP source/destination
port-range matches. Port ranges are converted
to a masked values and a flow entry is added
for each such combination of TCP and UDP
source/destination ports.

Change-Id: I297deee3d64be9c82a63f4156dd6d1185a890f83
Signed-off-by: ananth <ananth.y@hcl.com>
sfc/classifier/impl/src/main/java/org/opendaylight/netvirt/sfc/classifier/providers/OpenFlow13Provider.java
sfc/classifier/impl/src/main/java/org/opendaylight/netvirt/sfc/classifier/service/domain/impl/OpenflowRenderer.java
sfc/classifier/impl/src/main/java/org/opendaylight/netvirt/sfc/classifier/utils/AclMatches.java
sfc/classifier/impl/src/test/java/org/opendaylight/netvirt/sfc/classifier/providers/OpenFlow13ProviderTest.java
sfc/classifier/impl/src/test/java/org/opendaylight/netvirt/sfc/classifier/utils/AclMatchesTest.java
sfc/translator/src/main/java/org/opendaylight/netvirt/sfc/translator/flowclassifier/FlowClassifierTranslator.java

index c8c67d39b487fc076e63401e6ff737e5e3249b75..850df6204aecba65836dbd8a70478defbfde693d 100644 (file)
@@ -79,7 +79,7 @@ public class OpenFlow13Provider {
     public static final String OF_URI_SEPARATOR = ":";
     public static final Ipv4Address NULL_IP = new Ipv4Address("0.0.0.0");
 
-    public MatchBuilder getMatchBuilderFromAceMatches(Matches matches) {
+    public List<MatchBuilder> getMatchBuilderFromAceMatches(Matches matches) {
         if (matches == null) {
             return null;
         }
index b77059d4ffb94883600c4f4f6a39d998074fd33b..32b089f0ba0cfe9aef99e94b7bfba9cf1dd07f06 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.netvirt.sfc.classifier.service.domain.api.ClassifierEntr
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -103,11 +104,12 @@ public class OpenflowRenderer implements ClassifierEntryRenderer {
     @Override
     public void renderMatch(NodeId nodeId, String connector, Matches matches, Long nsp, Short nsi) {
         Long port = OpenFlow13Provider.getPortNoFromNodeConnector(connector);
-        Flow flow = this.openFlow13Provider.createIngressClassifierAclFlow(
-                nodeId, this.openFlow13Provider.getMatchBuilderFromAceMatches(matches), port, nsp, nsi);
-
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-            tx -> this.openFlow13Provider.appendFlowForCreate(nodeId, flow, tx)), LOG, "Error rendering a match");
+        List<MatchBuilder> matchBuilds = this.openFlow13Provider.getMatchBuilderFromAceMatches(matches);
+        for (MatchBuilder match : matchBuilds) {
+            Flow flow = this.openFlow13Provider.createIngressClassifierAclFlow(nodeId, match, port, nsp, nsi);
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                tx -> this.openFlow13Provider.appendFlowForCreate(nodeId, flow, tx)), LOG, "Error rendering a match");
+        }
     }
 
     @Override
@@ -175,11 +177,12 @@ public class OpenflowRenderer implements ClassifierEntryRenderer {
     @Override
     public void suppressMatch(NodeId nodeId, String connector, Matches matches, Long nsp, Short nsi) {
         Long port = OpenFlow13Provider.getPortNoFromNodeConnector(connector);
-        Flow flow = this.openFlow13Provider.createIngressClassifierAclFlow(
-                nodeId, this.openFlow13Provider.getMatchBuilderFromAceMatches(matches), port, nsp, nsi);
-
-        ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
-            tx -> this.openFlow13Provider.appendFlowForDelete(nodeId, flow, tx)), LOG, "Error deleting a match");
+        List<MatchBuilder> matchBuilds = this.openFlow13Provider.getMatchBuilderFromAceMatches(matches);
+        for (MatchBuilder match : matchBuilds) {
+            Flow flow = this.openFlow13Provider.createIngressClassifierAclFlow(nodeId, match, port, nsp, nsi);
+            ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
+                tx -> this.openFlow13Provider.appendFlowForDelete(nodeId, flow, tx)), LOG, "Error deleting a match");
+        }
     }
 
     @Override
index 7eabc80466a3eebfb3ba017fea060ae4494ad756..0a7b27798c4407673e28759b19ed677337819dca 100644 (file)
@@ -8,6 +8,15 @@
 
 package org.opendaylight.netvirt.sfc.classifier.utils;
 
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
@@ -42,20 +51,33 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfTcpDstKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfTcpSrcKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfUdpDstKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmOfUdpSrcKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.dst.grouping.NxmOfTcpDstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.src.grouping.NxmOfTcpSrcBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.udp.dst.grouping.NxmOfUdpDstBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.udp.src.grouping.NxmOfUdpSrcBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class AclMatches {
     private static final Logger LOG = LoggerFactory.getLogger(AclMatches.class);
-    private final MatchBuilder matchBuilder;
+    private MatchBuilder matchBuilder;
+    private List<GeneralAugMatchNodesNodeTableFlow> portMatches;
     private final Matches matches;
     private boolean ipv4EtherTypeSet;
     private boolean ipv6EtherTypeSet;
 
     public AclMatches(Matches matches) {
-        this.matchBuilder = new MatchBuilder();
         this.matches = matches;
         this.ipv4EtherTypeSet = false;
         this.ipv6EtherTypeSet = false;
@@ -65,16 +87,25 @@ public class AclMatches {
      * Convert the ACL into an OpenFlow {@link MatchBuilder}.
      * @return {@link MatchBuilder}
      */
-    public MatchBuilder buildMatch() {
+    public List<MatchBuilder> buildMatch() {
+        matchBuilder = new MatchBuilder();
+        portMatches = new ArrayList<>();
+        List<MatchBuilder> newMatches = new ArrayList<>();
         if (matches.getAceType() instanceof AceEth) {
             addEthMatch();
         } else if (matches.getAceType() instanceof AceIp) {
             addIpMatch();
         }
-
-        LOG.debug("buildMatch: {}", matchBuilder.build());
-
-        return matchBuilder;
+        if (portMatches.isEmpty()) {
+            newMatches.add(this.matchBuilder);
+        } else if (!portMatches.isEmpty()) {
+            for (GeneralAugMatchNodesNodeTableFlow portMatch : portMatches) {
+                newMatches.add(new MatchBuilder(matchBuilder.build())
+                    .addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, portMatch));
+            }
+        }
+        LOG.debug("returned matches: {}", newMatches);
+        return newMatches;
     }
 
     private void addEthMatch() {
@@ -136,42 +167,162 @@ public class AclMatches {
         ipMatch.setIpProtocol(aceIp.getProtocol());
         matchBuilder.setIpMatch(mergeIpMatch(matchBuilder, ipMatch));
 
-        // TODO Ranges are not supported yet
-
-        int srcPort = 0;
+        Integer srcPort = null;
         if (aceIp.getSourcePortRange() != null && aceIp.getSourcePortRange().getLowerPort() != null) {
             srcPort = aceIp.getSourcePortRange().getLowerPort().getValue();
         }
 
-        int dstPort = 0;
+        Integer srcPortMax = srcPort;
+        if (aceIp.getSourcePortRange() != null && aceIp.getSourcePortRange().getUpperPort() != null) {
+            srcPortMax = aceIp.getSourcePortRange().getUpperPort().getValue();
+        }
+
+        Integer dstPort = null;
         if (aceIp.getDestinationPortRange() != null && aceIp.getDestinationPortRange().getLowerPort() != null) {
             dstPort = aceIp.getDestinationPortRange().getLowerPort().getValue();
         }
 
+        Integer dstPortMax = dstPort;
+        if (aceIp.getDestinationPortRange() != null && aceIp.getDestinationPortRange().getUpperPort() != null) {
+            dstPortMax = aceIp.getDestinationPortRange().getUpperPort().getValue();
+        }
+
         // Match on a TCP/UDP src/dst port
-        if (aceIp.getProtocol() == IPProtocols.TCP.shortValue()) {
-            TcpMatchBuilder tcpMatch = new TcpMatchBuilder();
-            if (srcPort != 0) {
-                tcpMatch.setTcpSourcePort(new PortNumber(srcPort));
-            }
-            if (dstPort != 0) {
-                tcpMatch.setTcpDestinationPort(new PortNumber(dstPort));
+        if (srcPort != null || dstPort != null) {
+            Map<Integer,Integer> srcPortMaskMap = srcPort == null ? Collections.singletonMap(0, 0) :
+                getLayer4MaskForRange(srcPort, srcPortMax);
+            Map<Integer,Integer> dstPortMaskMap = dstPort == null ? Collections.singletonMap(0, 0) :
+                getLayer4MaskForRange(dstPort, dstPortMax);
+            Set<List<Map.Entry<Integer,Integer>>> srcDstMatches = Sets
+                .cartesianProduct(srcPortMaskMap.entrySet(), dstPortMaskMap.entrySet());
+            if (aceIp.getProtocol() == IPProtocols.TCP.shortValue()) {
+                portMatches = srcDstMatches.stream().map(srcDstPairList -> buildTcpMatch(srcDstPairList
+                    .get(0), srcDstPairList.get(1))).collect(Collectors.toList());
+            } else if (aceIp.getProtocol() == IPProtocols.UDP.shortValue()) {
+                portMatches = srcDstMatches.stream().map(srcDstPairList -> buildUdpMatch(srcDstPairList
+                    .get(0), srcDstPairList.get(1))).collect(Collectors.toList());
             }
-            if (srcPort != 0 || dstPort != 0) {
-                matchBuilder.setLayer4Match(tcpMatch.build());
-            }
-        } else if (aceIp.getProtocol() == IPProtocols.UDP.shortValue()) {
-            UdpMatchBuilder udpMatch = new UdpMatchBuilder();
-            if (srcPort != 0) {
-                udpMatch.setUdpSourcePort(new PortNumber(srcPort));
+        }
+    }
+
+    private static GeneralAugMatchNodesNodeTableFlow buildTcpMatch(Map.Entry<Integer,Integer> srcEntry,
+        Map.Entry<Integer,Integer> dstEntry) {
+        List<ExtensionList> srcDstExtList = new ArrayList<>();
+
+        if (srcEntry.getValue() != 0) {
+            NxmOfTcpSrcBuilder tcpSrc = new NxmOfTcpSrcBuilder();
+            tcpSrc.setMask(srcEntry.getValue());
+            tcpSrc.setPort(new PortNumber(srcEntry.getKey()));
+            NxAugMatchNodesNodeTableFlow nxAugMatchTcpSrc =
+                new NxAugMatchNodesNodeTableFlowBuilder().setNxmOfTcpSrc(tcpSrc.build()).build();
+            srcDstExtList.add(new ExtensionListBuilder().setExtensionKey(NxmOfTcpSrcKey.class)
+                .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class,
+                    nxAugMatchTcpSrc).build()).build());
+        }
+
+        if (dstEntry.getValue() != 0) {
+            NxmOfTcpDstBuilder tcpDst = new NxmOfTcpDstBuilder();
+            tcpDst.setMask(dstEntry.getValue());
+            tcpDst.setPort(new PortNumber(dstEntry.getKey()));
+            NxAugMatchNodesNodeTableFlow nxAugMatchTcpDst =
+                new NxAugMatchNodesNodeTableFlowBuilder().setNxmOfTcpDst(tcpDst.build()).build();
+            srcDstExtList.add(new ExtensionListBuilder().setExtensionKey(NxmOfTcpDstKey.class)
+                .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class,
+                    nxAugMatchTcpDst).build()).build());
+        }
+
+        GeneralAugMatchNodesNodeTableFlow genAugMatch =
+            new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(srcDstExtList).build();
+
+        return genAugMatch;
+    }
+
+    private static GeneralAugMatchNodesNodeTableFlow buildUdpMatch(Map.Entry<Integer,Integer> srcEntry,
+        Map.Entry<Integer,Integer> dstEntry) {
+        List<ExtensionList> srcDstExtList = new ArrayList<>();
+
+        if (srcEntry.getValue() != 0) {
+            NxmOfUdpSrcBuilder udpSrc = new NxmOfUdpSrcBuilder();
+            udpSrc.setMask(srcEntry.getValue());
+            udpSrc.setPort(new PortNumber(srcEntry.getKey()));
+            NxAugMatchNodesNodeTableFlow nxAugMatchUdpSrc =
+                new NxAugMatchNodesNodeTableFlowBuilder().setNxmOfUdpSrc(udpSrc.build()).build();
+            srcDstExtList.add(new ExtensionListBuilder().setExtensionKey(NxmOfUdpSrcKey.class)
+                .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class,
+                    nxAugMatchUdpSrc).build()).build());
+        }
+
+        if (dstEntry.getValue() != 0) {
+            NxmOfUdpDstBuilder udpDst = new NxmOfUdpDstBuilder();
+            udpDst.setMask(dstEntry.getValue());
+            udpDst.setPort(new PortNumber(dstEntry.getKey()));
+            NxAugMatchNodesNodeTableFlow nxAugMatchUdpDst =
+                new NxAugMatchNodesNodeTableFlowBuilder().setNxmOfUdpDst(udpDst.build()).build();
+            srcDstExtList.add(new ExtensionListBuilder().setExtensionKey(NxmOfUdpDstKey.class)
+                .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class,
+                    nxAugMatchUdpDst).build()).build());
+        }
+
+        GeneralAugMatchNodesNodeTableFlow genAugMatch =
+            new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(srcDstExtList).build();
+
+        return genAugMatch;
+    }
+
+    public static Map<Integer,Integer>  getLayer4MaskForRange(int portMin, int portMax) {
+        final int[] offset = { 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 };
+        final int[] mask = { 0x8000, 0xC000, 0xE000, 0xF000, 0xF800, 0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
+            0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF };
+        int noOfPorts = portMax - portMin + 1;
+        Map<Integer,Integer> portMap = new HashMap<>();
+        if (noOfPorts == 1) {
+            portMap.put(portMin, mask[15]);
+            return portMap;
+        } else if (noOfPorts == 65535) {
+            portMap.put(portMin, 0x0000);
+            return portMap;
+        }
+        if (noOfPorts < 0) { // TODO: replace with infrautils.counter in case of high repetitive usage
+            LOG.warn("Cannot convert port range into a set of masked port ranges - Illegal port range {}-{}", portMin,
+                    portMax);
+            return portMap;
+        }
+        String binaryNoOfPorts = Integer.toBinaryString(noOfPorts);
+        if (binaryNoOfPorts.length() > 16) { // TODO: replace with infrautils.counter in case of high repetitive usage
+            LOG.warn("Cannot convert port range into a set of masked port ranges - Illegal port range {}-{}", portMin,
+                    portMax);
+            return portMap;
+        }
+        int medianOffset = 16 - binaryNoOfPorts.length();
+        int medianLength = offset[medianOffset];
+        int median = 0;
+        for (int tempMedian = 0;tempMedian < portMax;) {
+            tempMedian = medianLength + tempMedian;
+            if (portMin < tempMedian) {
+                median = tempMedian;
+                break;
             }
-            if (dstPort != 0) {
-                udpMatch.setUdpDestinationPort(new PortNumber(dstPort));
+        }
+        int tempMedian = 0;
+        int currentMedain = median;
+        for (int tempMedianOffset = medianOffset;16 > tempMedianOffset;tempMedianOffset++) {
+            tempMedian = currentMedain - offset[tempMedianOffset];
+            for (;portMin <= tempMedian;) {
+                portMap.put(tempMedian, mask[tempMedianOffset]);
+                currentMedain = tempMedian;
+                tempMedian = tempMedian - offset[tempMedianOffset];
             }
-            if (srcPort != 0 || dstPort != 0) {
-                matchBuilder.setLayer4Match(udpMatch.build());
+        }
+        currentMedain = median;
+        for (int tempMedianOffset = medianOffset;16 > tempMedianOffset;tempMedianOffset++) {
+            tempMedian = currentMedain + offset[tempMedianOffset];
+            for (;portMax >= tempMedian - 1;) {
+                portMap.put(currentMedain, mask[tempMedianOffset]);
+                currentMedain = tempMedian;
+                tempMedian = tempMedian  + offset[tempMedianOffset];
             }
         }
+        return portMap;
     }
 
     private void addIpV4Match(AceIp aceIp) {
index 8587ac625a674b4bda0885346996c90c9d3c236b..d869c801e6415fa0febccd9da3d66d458b2bf24e 100644 (file)
@@ -184,28 +184,31 @@ public class OpenFlow13ProviderTest {
         MatchesBuilder matchesBuilder = new MatchesBuilder();
         matchesBuilder.setAceType(new AceIpBuilder().build());
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
 
-        Flow flow = openflowProvider.createIngressClassifierAclFlow(
-                nodeId, matchBuilder, IN_PORT, NSP, NSI);
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
 
-        assertEquals(flow.getTableId().shortValue(), NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE);
-        assertEquals(flow.getPriority().intValue(), OpenFlow13Provider.INGRESS_CLASSIFIER_ACL_MATCH_PRIORITY);
-        assertEquals(flow.getId().getValue(),
-                OpenFlow13Provider.INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue()
-                + matchBuilder.build().toString());
-        assertEquals(flow.getCookie().getValue(), OpenFlow13Provider.INGRESS_CLASSIFIER_ACL_COOKIE);
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            Flow flow = openflowProvider.createIngressClassifierAclFlow(
+                    nodeId, matchBuilder, IN_PORT, NSP, NSI);
 
-        // Only checking the inport match, since the rest is tested in AclMatchesTest
-        checkMatchInport(flow.getMatch(), nodeId.getValue() + ":" + IN_PORT);
+            assertEquals(flow.getTableId().shortValue(), NwConstants.INGRESS_SFC_CLASSIFIER_ACL_TABLE);
+            assertEquals(flow.getPriority().intValue(), OpenFlow13Provider.INGRESS_CLASSIFIER_ACL_MATCH_PRIORITY);
+            assertEquals(flow.getId().getValue(),
+                    OpenFlow13Provider.INGRESS_CLASSIFIER_ACL_FLOW_NAME + "_" + nodeId.getValue()
+                    + matchBuilder.build().toString());
+            assertEquals(flow.getCookie().getValue(), OpenFlow13Provider.INGRESS_CLASSIFIER_ACL_COOKIE);
 
-        assertEquals(1, flow.getInstructions().getInstruction().size());
-        Instruction curInstruction = flow.getInstructions().getInstruction().get(0).getInstruction();
-        List<Action> actionList = checkApplyActionSize(curInstruction, 3);
+            // Only checking the inport match, since the rest is tested in AclMatchesTest
+            checkMatchInport(flow.getMatch(), nodeId.getValue() + ":" + IN_PORT);
 
-        checkActionLoadReg(actionList.get(0), NxmNxReg2.class, 8, 31, NSP);
-        checkActionLoadReg(actionList.get(1), NxmNxReg2.class, 0, 7, NSI);
-        checkActionResubmit(curInstruction, NwConstants.LPORT_DISPATCHER_TABLE);
+            assertEquals(1, flow.getInstructions().getInstruction().size());
+            Instruction curInstruction = flow.getInstructions().getInstruction().get(0).getInstruction();
+            List<Action> actionList = checkApplyActionSize(curInstruction, 3);
+
+            checkActionLoadReg(actionList.get(0), NxmNxReg2.class, 8, 31, NSP);
+            checkActionLoadReg(actionList.get(1), NxmNxReg2.class, 0, 7, NSI);
+            checkActionResubmit(curInstruction, NwConstants.LPORT_DISPATCHER_TABLE);
+        }
     }
 
     @Test
index 5a25d8ac12245b421082ebed6fdaa9a0f3fd8d33..8b53813fb4d8dda75b3efaf8bc10f43f82aa3123 100644 (file)
@@ -12,7 +12,12 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import org.junit.Test;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
@@ -40,8 +45,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.dst.grouping.NxmOfTcpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.tcp.src.grouping.NxmOfTcpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.udp.dst.grouping.NxmOfUdpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.of.udp.src.grouping.NxmOfUdpSrc;
 
 public class AclMatchesTest {
 
@@ -51,14 +60,14 @@ public class AclMatchesTest {
     private static final String IPV4_SRC_STR = "10.1.2.3/32";
     private static final String IPV6_DST_STR = "2001:DB8:AC10:FE01::/64";
     private static final String IPV6_SRC_STR = "2001:db8:85a3:7334::/64";
-    private static final int TCP_SRC_LOWER_PORT = 1234;
-    private static final int TCP_SRC_UPPER_PORT = 2345;
-    private static final int TCP_DST_LOWER_PORT = 80;
+    private static final int TCP_SRC_LOWER_PORT = 80;
+    private static final int TCP_SRC_UPPER_PORT = 82;
+    private static final int TCP_DST_LOWER_PORT = 800;
     private static final int TCP_DST_UPPER_PORT = 800;
     private static final int UDP_SRC_LOWER_PORT = 90;
-    private static final int UDP_SRC_UPPER_PORT = 900;
-    private static final int UDP_DST_LOWER_PORT = 90;
-    private static final int UDP_DST_UPPER_PORT = 900;
+    private static final int UDP_SRC_UPPER_PORT = 90;
+    private static final int UDP_DST_LOWER_PORT = 900;
+    private static final int UDP_DST_UPPER_PORT = 902;
     private static final short DSCP_VALUE = (short) 42;
 
 
@@ -73,18 +82,20 @@ public class AclMatchesTest {
 
         // Create the aclMatches that is the object to be tested
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
-
-        // The ethernet match should be there with src/dst values
-        EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
-        assertNotNull(ethMatch);
-        assertEquals(ethMatch.getEthernetSource().getAddress().getValue(), MAC_SRC_STR);
-        assertEquals(ethMatch.getEthernetDestination().getAddress().getValue(), MAC_DST_STR);
-
-        // The rest should be null
-        assertNull(matchBuilder.getIpMatch());
-        assertNull(matchBuilder.getLayer3Match());
-        assertNull(matchBuilder.getLayer4Match());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // The ethernet match should be there with src/dst values
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetSource().getAddress().getValue(), MAC_SRC_STR);
+            assertEquals(ethMatch.getEthernetDestination().getAddress().getValue(), MAC_DST_STR);
+
+            // The rest should be null
+            assertNull(matchBuilder.getIpMatch());
+            assertNull(matchBuilder.getLayer3Match());
+            assertNull(matchBuilder.getLayer4Match());
+        }
     }
 
     @Test
@@ -101,22 +112,218 @@ public class AclMatchesTest {
 
         // Create the aclMatches that is the object to be tested
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
-
-        // The layer3 match should be there with src/dst values
-        Ipv4Match l3 = (Ipv4Match) matchBuilder.getLayer3Match();
-        assertNotNull(l3);
-        assertEquals(l3.getIpv4Destination().getValue().toString(), IPV4_DST_STR);
-        assertEquals(l3.getIpv4Source().getValue().toString(), IPV4_SRC_STR);
-
-        // There should be an IPv4 etherType set
-        EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
-        assertNotNull(ethMatch);
-        assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
-
-        // The rest should be null
-        assertNull(matchBuilder.getIpMatch());
-        assertNull(matchBuilder.getLayer4Match());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // The layer3 match should be there with src/dst values
+            Ipv4Match l3 = (Ipv4Match) matchBuilder.getLayer3Match();
+            assertNotNull(l3);
+            assertEquals(l3.getIpv4Destination().getValue().toString(), IPV4_DST_STR);
+            assertEquals(l3.getIpv4Source().getValue().toString(), IPV4_SRC_STR);
+
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // The rest should be null
+            assertNull(matchBuilder.getIpMatch());
+            assertNull(matchBuilder.getLayer4Match());
+        }
+        assertEquals(1, matchBuilds.size());
+    }
+
+    @Test
+    public void buildIpv4SrcLwrTcpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.TCP.shortValue());
+
+        SourcePortRangeBuilder srcPortRange = new SourcePortRangeBuilder();
+        srcPortRange.setLowerPort(new PortNumber(TCP_SRC_LOWER_PORT));
+        aceIpBuilder.setSourcePortRange(srcPortRange.build());
+
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
+
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> srcTcpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its TCP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.TCP.shortValue()));
+
+            NxmOfTcpSrc tcpSrc = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfTcpSrc();
+
+
+            if (tcpSrc != null) {
+                srcTcpMatches.add(tcpSrc.getPort().getValue());
+                srcTcpMatches.add(tcpSrc.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(1, matchBuilds.size());
+        assertEquals(2, srcTcpMatches.size());
+        assertTrue(srcTcpMatches.contains(TCP_SRC_LOWER_PORT));
+        assertTrue(srcTcpMatches.contains(65535));
+    }
+
+    @Test
+    public void buildIpv4SrcTcpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.TCP.shortValue());
+
+        SourcePortRangeBuilder srcPortRange = new SourcePortRangeBuilder();
+        srcPortRange.setLowerPort(new PortNumber(TCP_SRC_LOWER_PORT));
+        srcPortRange.setUpperPort(new PortNumber(TCP_SRC_UPPER_PORT));
+        aceIpBuilder.setSourcePortRange(srcPortRange.build());
+
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
+
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> srcTcpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its TCP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.TCP.shortValue()));
+
+            NxmOfTcpSrc tcpSrc = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfTcpSrc();
+
+
+            if (tcpSrc != null) {
+                srcTcpMatches.add(tcpSrc.getPort().getValue());
+                srcTcpMatches.add(tcpSrc.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(2, matchBuilds.size());
+        assertEquals(4, srcTcpMatches.size());
+        assertTrue(srcTcpMatches.contains(TCP_SRC_LOWER_PORT));
+        assertTrue(srcTcpMatches.contains(TCP_SRC_UPPER_PORT));
+        assertTrue(srcTcpMatches.contains(65535));
+        assertTrue(srcTcpMatches.contains(65534));
+    }
+
+    @Test
+    public void buildIpv4DstLwrTcpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.TCP.shortValue());
+
+        DestinationPortRangeBuilder dstPortRange = new DestinationPortRangeBuilder();
+        dstPortRange.setLowerPort(new PortNumber(TCP_DST_LOWER_PORT));
+        aceIpBuilder.setDestinationPortRange(dstPortRange.build());
+
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
+
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> dstTcpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its TCP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.TCP.shortValue()));
+
+            NxmOfTcpDst tcpDst = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfTcpDst();
+
+            if (tcpDst != null) {
+                dstTcpMatches.add(tcpDst.getPort().getValue());
+                dstTcpMatches.add(tcpDst.getMask());
+            }
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(1, matchBuilds.size());
+        assertEquals(2, dstTcpMatches.size());
+        assertTrue(dstTcpMatches.contains(TCP_DST_LOWER_PORT));
+        assertTrue(dstTcpMatches.contains(65535));
+    }
+
+    @Test
+    public void buildIpv4DstTcpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.TCP.shortValue());
+
+        DestinationPortRangeBuilder dstPortRange = new DestinationPortRangeBuilder();
+        dstPortRange.setLowerPort(new PortNumber(TCP_DST_LOWER_PORT));
+        dstPortRange.setUpperPort(new PortNumber(TCP_DST_UPPER_PORT));
+        aceIpBuilder.setDestinationPortRange(dstPortRange.build());
+
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
+
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> dstTcpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its TCP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.TCP.shortValue()));
+
+            NxmOfTcpDst tcpDst = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfTcpDst();
+
+            if (tcpDst != null) {
+                dstTcpMatches.add(tcpDst.getPort().getValue());
+                dstTcpMatches.add(tcpDst.getMask());
+            }
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(1, matchBuilds.size());
+        assertEquals(2, dstTcpMatches.size());
+        assertTrue(dstTcpMatches.contains(TCP_DST_LOWER_PORT));
+        assertTrue(dstTcpMatches.contains(TCP_DST_UPPER_PORT));
+        assertTrue(dstTcpMatches.contains(65535));
     }
 
     @Test
@@ -138,31 +345,107 @@ public class AclMatchesTest {
         MatchesBuilder matchesBuilder = new MatchesBuilder();
         matchesBuilder.setAceType(aceIpBuilder.build());
 
-        // Create the aclMatches that is the object to be tested
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> dstTcpMatches = new HashSet<>();
+        Set<Integer> srcTcpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its TCP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.TCP.shortValue()));
+
+            NxmOfTcpSrc tcpSrc = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfTcpSrc();
+
+            NxmOfTcpDst tcpDst = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(1)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfTcpDst();
+
+            if (tcpSrc != null) {
+                srcTcpMatches.add(tcpSrc.getPort().getValue());
+                srcTcpMatches.add(tcpSrc.getMask());
+            }
+
+            if (tcpDst != null) {
+                dstTcpMatches.add(tcpDst.getPort().getValue());
+                dstTcpMatches.add(tcpDst.getMask());
+            }
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(2, matchBuilds.size());
+        assertEquals(4, srcTcpMatches.size());
+        assertEquals(2, dstTcpMatches.size());
+
+        assertTrue(srcTcpMatches.contains(TCP_SRC_LOWER_PORT));
+        assertTrue(srcTcpMatches.contains(TCP_SRC_UPPER_PORT));
+        assertTrue(srcTcpMatches.contains(65535));
+        assertTrue(srcTcpMatches.contains(65534));
+
+        assertTrue(dstTcpMatches.contains(TCP_DST_LOWER_PORT));
+        assertTrue(dstTcpMatches.contains(TCP_DST_UPPER_PORT));
+        assertTrue(dstTcpMatches.contains(65535));
+    }
 
-        // There should be an IPv4 etherType set
-        EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
-        assertNotNull(ethMatch);
-        assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+    @Test
+    public void buildIpv4SrcLwrUdpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.UDP.shortValue());
 
-        // Make sure its TCP
-        IpMatch ipMatch = matchBuilder.getIpMatch();
-        assertNotNull(ipMatch);
-        assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.TCP.shortValue()));
+        SourcePortRangeBuilder srcPortRange = new SourcePortRangeBuilder();
+        srcPortRange.setLowerPort(new PortNumber(UDP_SRC_LOWER_PORT));
+        aceIpBuilder.setSourcePortRange(srcPortRange.build());
 
-        // Currently ranges arent supported, only the lower port is used
-        TcpMatch tcpMatch = (TcpMatch) matchBuilder.getLayer4Match();
-        assertEquals(tcpMatch.getTcpSourcePort().getValue(), Integer.valueOf(TCP_SRC_LOWER_PORT));
-        assertEquals(tcpMatch.getTcpDestinationPort().getValue(), Integer.valueOf(TCP_DST_LOWER_PORT));
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
 
-        // The layer3 match should be null
-        assertNull(matchBuilder.getLayer3Match());
+        // Create the aclMatches that is the object to be tested
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> srcUdpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its UDP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.UDP.shortValue()));
+
+            NxmOfUdpSrc udpSrc = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfUdpSrc();
+
+            if (udpSrc != null) {
+                srcUdpMatches.add(udpSrc.getPort().getValue());
+                srcUdpMatches.add(udpSrc.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(1, matchBuilds.size());
+        assertEquals(2, srcUdpMatches.size());
+        assertTrue(srcUdpMatches.contains(UDP_SRC_LOWER_PORT));
+        assertTrue(srcUdpMatches.contains(65535));
     }
 
     @Test
-    public void buildIpv4UdpMatchTest() {
+    public void buildIpv4SrcUdpMatchTest() {
         AceIpBuilder aceIpBuilder = new AceIpBuilder();
         aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
         aceIpBuilder.setProtocol(IPProtocols.UDP.shortValue());
@@ -172,9 +455,53 @@ public class AclMatchesTest {
         srcPortRange.setUpperPort(new PortNumber(UDP_SRC_UPPER_PORT));
         aceIpBuilder.setSourcePortRange(srcPortRange.build());
 
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
+
+        // Create the aclMatches that is the object to be tested
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> srcUdpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its UDP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.UDP.shortValue()));
+
+            NxmOfUdpSrc udpSrc = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfUdpSrc();
+
+            if (udpSrc != null) {
+                srcUdpMatches.add(udpSrc.getPort().getValue());
+                srcUdpMatches.add(udpSrc.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(1, matchBuilds.size());
+        assertEquals(2, srcUdpMatches.size());
+        assertTrue(srcUdpMatches.contains(UDP_SRC_LOWER_PORT));
+        assertTrue(srcUdpMatches.contains(UDP_SRC_UPPER_PORT));
+        assertTrue(srcUdpMatches.contains(65535));
+    }
+
+    @Test
+    public void buildIpv4DstLwrUdpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.UDP.shortValue());
+
         DestinationPortRangeBuilder dstPortRange = new DestinationPortRangeBuilder();
         dstPortRange.setLowerPort(new PortNumber(UDP_DST_LOWER_PORT));
-        dstPortRange.setUpperPort(new PortNumber(UDP_DST_UPPER_PORT));
         aceIpBuilder.setDestinationPortRange(dstPortRange.build());
 
         MatchesBuilder matchesBuilder = new MatchesBuilder();
@@ -182,53 +509,190 @@ public class AclMatchesTest {
 
         // Create the aclMatches that is the object to be tested
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> dstUdpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its UDP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.UDP.shortValue()));
+
+            NxmOfUdpDst udpDst = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfUdpDst();
+
+            if (udpDst != null) {
+                dstUdpMatches.add(udpDst.getPort().getValue());
+                dstUdpMatches.add(udpDst.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(1, matchBuilds.size());
+        assertEquals(2, dstUdpMatches.size());
+        assertTrue(dstUdpMatches.contains(UDP_DST_LOWER_PORT));
+        assertTrue(dstUdpMatches.contains(65535));
+    }
 
-        // There should be an IPv4 etherType set
-        EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
-        assertNotNull(ethMatch);
-        assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+    @Test
+    public void buildIpv4DstUdpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setProtocol(IPProtocols.UDP.shortValue());
 
-        // Make sure its UDP
-        IpMatch ipMatch = matchBuilder.getIpMatch();
-        assertNotNull(ipMatch);
-        assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.UDP.shortValue()));
+        DestinationPortRangeBuilder dstPortRange = new DestinationPortRangeBuilder();
+        dstPortRange.setLowerPort(new PortNumber(UDP_DST_LOWER_PORT));
+        dstPortRange.setUpperPort(new PortNumber(UDP_DST_UPPER_PORT));
+        aceIpBuilder.setDestinationPortRange(dstPortRange.build());
 
-        // Currently ranges arent supported, only the lower port is used
-        UdpMatch udpMatch = (UdpMatch) matchBuilder.getLayer4Match();
-        assertEquals(udpMatch.getUdpSourcePort().getValue(), Integer.valueOf(UDP_SRC_LOWER_PORT));
-        assertEquals(udpMatch.getUdpDestinationPort().getValue(), Integer.valueOf(UDP_DST_LOWER_PORT));
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
 
-        // The layer3 match should be null
-        assertNull(matchBuilder.getLayer3Match());
+        // Create the aclMatches that is the object to be tested
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> dstUdpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its UDP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.UDP.shortValue()));
+
+            NxmOfUdpDst udpDst = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfUdpDst();
+
+            if (udpDst != null) {
+                dstUdpMatches.add(udpDst.getPort().getValue());
+                dstUdpMatches.add(udpDst.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(2, matchBuilds.size());
+        assertEquals(4, dstUdpMatches.size());
+        assertTrue(dstUdpMatches.contains(UDP_DST_LOWER_PORT));
+        assertTrue(dstUdpMatches.contains(UDP_DST_UPPER_PORT));
+        assertTrue(dstUdpMatches.contains(65534));
+        assertTrue(dstUdpMatches.contains(65535));
     }
 
     @Test
-    public void buildIpv4DscpMatchTest() {
+    public void buildIpv4UdpMatchTest() {
         AceIpBuilder aceIpBuilder = new AceIpBuilder();
         aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
-        aceIpBuilder.setDscp(new Dscp(DSCP_VALUE));
+        aceIpBuilder.setProtocol(IPProtocols.UDP.shortValue());
+
+        SourcePortRangeBuilder srcPortRange = new SourcePortRangeBuilder();
+        srcPortRange.setLowerPort(new PortNumber(UDP_SRC_LOWER_PORT));
+        srcPortRange.setUpperPort(new PortNumber(UDP_SRC_UPPER_PORT));
+        aceIpBuilder.setSourcePortRange(srcPortRange.build());
+
+        DestinationPortRangeBuilder dstPortRange = new DestinationPortRangeBuilder();
+        dstPortRange.setLowerPort(new PortNumber(UDP_DST_LOWER_PORT));
+        dstPortRange.setUpperPort(new PortNumber(UDP_DST_UPPER_PORT));
+        aceIpBuilder.setDestinationPortRange(dstPortRange.build());
 
         MatchesBuilder matchesBuilder = new MatchesBuilder();
         matchesBuilder.setAceType(aceIpBuilder.build());
 
         // Create the aclMatches that is the object to be tested
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        Set<Integer> srcUdpMatches = new HashSet<>();
+        Set<Integer> dstUdpMatches = new HashSet<>();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Make sure its UDP
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpProtocol(), Short.valueOf(IPProtocols.UDP.shortValue()));
+
+            NxmOfUdpSrc udpSrc = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(0)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfUdpSrc();
+
+            NxmOfUdpDst udpDst = matchBuilder
+                    .augmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList().get(1)
+                    .getExtension().augmentation(NxAugMatchNodesNodeTableFlow.class).getNxmOfUdpDst();
+
+            if (udpSrc != null) {
+                srcUdpMatches.add(udpSrc.getPort().getValue());
+                srcUdpMatches.add(udpSrc.getMask());
+            }
+
+            if (udpDst != null) {
+                dstUdpMatches.add(udpDst.getPort().getValue());
+                dstUdpMatches.add(udpDst.getMask());
+            }
+
+            // The layer3 match should be null
+            assertNull(matchBuilder.getLayer3Match());
+        }
+        assertEquals(2, matchBuilds.size());
+        assertEquals(2, srcUdpMatches.size());
+        assertEquals(4, dstUdpMatches.size());
+
+        assertTrue(srcUdpMatches.contains(UDP_SRC_LOWER_PORT));
+        assertTrue(srcUdpMatches.contains(UDP_SRC_UPPER_PORT));
+        assertTrue(srcUdpMatches.contains(65535));
+
+        assertTrue(dstUdpMatches.contains(UDP_DST_LOWER_PORT));
+        assertTrue(dstUdpMatches.contains(UDP_DST_UPPER_PORT));
+        assertTrue(dstUdpMatches.contains(65534));
+        assertTrue(dstUdpMatches.contains(65535));
+    }
 
-        // There should be an IPv4 etherType set
-        EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
-        assertNotNull(ethMatch);
-        assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+    @Test
+    public void buildIpv4DscpMatchTest() {
+        AceIpBuilder aceIpBuilder = new AceIpBuilder();
+        aceIpBuilder.setAceIpVersion(new AceIpv4Builder().build());
+        aceIpBuilder.setDscp(new Dscp(DSCP_VALUE));
 
-        // Check the DSCP value
-        IpMatch ipMatch = matchBuilder.getIpMatch();
-        assertNotNull(ipMatch);
-        assertEquals(ipMatch.getIpDscp().getValue(), Short.valueOf(DSCP_VALUE));
+        MatchesBuilder matchesBuilder = new MatchesBuilder();
+        matchesBuilder.setAceType(aceIpBuilder.build());
 
-        // The rest should be null
-        assertNull(matchBuilder.getLayer3Match());
-        assertNull(matchBuilder.getLayer4Match());
+        // Create the aclMatches that is the object to be tested
+        AclMatches aclMatches = new AclMatches(matchesBuilder.build());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // There should be an IPv4 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV4));
+
+            // Check the DSCP value
+            IpMatch ipMatch = matchBuilder.getIpMatch();
+            assertNotNull(ipMatch);
+            assertEquals(ipMatch.getIpDscp().getValue(), Short.valueOf(DSCP_VALUE));
+
+            // The rest should be null
+            assertNull(matchBuilder.getLayer3Match());
+            assertNull(matchBuilder.getLayer4Match());
+        }
     }
 
     @Test
@@ -245,22 +709,24 @@ public class AclMatchesTest {
 
         // Create the aclMatches that is the object to be tested
         AclMatches aclMatches = new AclMatches(matchesBuilder.build());
-        MatchBuilder matchBuilder = aclMatches.buildMatch();
-
-        // The layer3 match should be there with src/dst values
-        Ipv6Match l3 = (Ipv6Match) matchBuilder.getLayer3Match();
-        assertNotNull(l3);
-        assertEquals(l3.getIpv6Destination().getValue().toString(), IPV6_DST_STR);
-        assertEquals(l3.getIpv6Source().getValue().toString(), IPV6_SRC_STR);
-
-        // There should be an IPv6 etherType set
-        EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
-        assertNotNull(ethMatch);
-        assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV6));
-
-        // The rest should be null
-        assertNull(matchBuilder.getIpMatch());
-        assertNull(matchBuilder.getLayer4Match());
+        List<MatchBuilder> matchBuilds = aclMatches.buildMatch();
+
+        for (MatchBuilder matchBuilder : matchBuilds) {
+            // The layer3 match should be there with src/dst values
+            Ipv6Match l3 = (Ipv6Match) matchBuilder.getLayer3Match();
+            assertNotNull(l3);
+            assertEquals(l3.getIpv6Destination().getValue().toString(), IPV6_DST_STR);
+            assertEquals(l3.getIpv6Source().getValue().toString(), IPV6_SRC_STR);
+
+            // There should be an IPv6 etherType set
+            EthernetMatch ethMatch = matchBuilder.getEthernetMatch();
+            assertNotNull(ethMatch);
+            assertEquals(ethMatch.getEthernetType().getType().getValue(), Long.valueOf(NwConstants.ETHTYPE_IPV6));
+
+            // The rest should be null
+            assertNull(matchBuilder.getIpMatch());
+            assertNull(matchBuilder.getLayer4Match());
+        }
     }
 
     @Test
@@ -377,4 +843,35 @@ public class AclMatchesTest {
         assertEquals(invertedAceIpv6.getDestinationIpv6Network(), aceIpv6.getSourceIpv6Network());
         assertEquals(invertedAceIpv6.getSourceIpv6Network(), aceIpv6.getDestinationIpv6Network());
     }
+
+    @Test
+    public void testgetLayer4MaskForRange_SinglePort() {
+        Map<Integer, Integer> layer4MaskForRange = AclMatches.getLayer4MaskForRange(1111, 1111);
+        assertEquals("port L4 mask missing", 1, layer4MaskForRange.size());
+    }
+
+    @Test
+    public void testgetLayer4MaskForRange_MultiplePorts() {
+        Map<Integer, Integer> layer4MaskForRange = AclMatches.getLayer4MaskForRange(1024, 2048);
+        assertEquals("port L4 mask missing", 2, layer4MaskForRange.size());
+    }
+
+    @Test
+    public void testgetLayer4MaskForRange_IllegalPortRange_ExceedMin() {
+        Map<Integer, Integer> layer4MaskForRange = AclMatches.getLayer4MaskForRange(0, 1);
+
+        assertEquals("port L4 mask missing", 1, layer4MaskForRange.size());
+    }
+
+    @Test
+    public void testgetLayer4MaskForRange_IllegalPortRange_ExceedMax() {
+        Map<Integer, Integer> layer4MaskForRange = AclMatches.getLayer4MaskForRange(1, 65536);
+        assertEquals("Illegal ports range", 0, layer4MaskForRange.size());
+    }
+
+    @Test
+    public void testgetLayer4MaskForRange_IllegalPortRange_MinGreaterThanMax() {
+        Map<Integer, Integer> layer4MaskForRange = AclMatches.getLayer4MaskForRange(8192, 4096);
+        assertEquals("Illegal ports range", 0, layer4MaskForRange.size());
+    }
 }
index 700dc12daeb1b1d11a457619eecce8194377d4b5..810110ef0842ebe98c17062e9eef18142e67ff5a 100644 (file)
@@ -123,6 +123,7 @@ public final class FlowClassifierTranslator {
         }
         if (flowClassifier.getSourcePortRangeMax() != null) {
             sourcePortRangeBuilder.setUpperPort(new PortNumber(flowClassifier.getSourcePortRangeMax()));
+            aceIpBuilder.setSourcePortRange(sourcePortRangeBuilder.build());
         }
         if (flowClassifier.getDestinationPortRangeMin() != null) {
             destinationPortRange.setLowerPort(new PortNumber(flowClassifier.getDestinationPortRangeMin()));
@@ -131,6 +132,7 @@ public final class FlowClassifierTranslator {
         }
         if (flowClassifier.getDestinationPortRangeMax() != null) {
             destinationPortRange.setUpperPort(new PortNumber(flowClassifier.getDestinationPortRangeMax()));
+            aceIpBuilder.setDestinationPortRange(destinationPortRange.build());
         }
         if (flowClassifier.getLogicalSourcePort() != null) {
             neutronPortsBuilder.setSourcePortUuid(flowClassifier.getLogicalSourcePort().getValue());