Merge "Bug:3026 - Echo response timeout needs be exported to configuration"
authorKamal Rameshan <kramesha@cisco.com>
Wed, 9 Mar 2016 17:33:00 +0000 (17:33 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 9 Mar 2016 17:33:00 +0000 (17:33 +0000)
14 files changed:
applications/statistics-manager/src/main/java/org/opendaylight/openflowplugin/applications/statistics/manager/impl/helper/MatchComparatorHelper.java
applications/statistics-manager/src/test/java/org/opendaylight/openflowplugin/applications/statistics/manager/impl/helper/MatchComparatorHelperTest.java
model/model-flow-base/src/main/yang/opendaylight-arbitrary-bitmask-fields.yang [new file with mode: 0644]
model/model-flow-base/src/main/yang/opendaylight-match-types.yang
model/pom.xml
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MdSalRegistratorUtils.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/IpConversionUtil.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertorImpl.java
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/IpConversionUtilTest.java
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertorImpl2Test.java
openflowplugin/src/test/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertorImplV13Test.java

index c6e97f1120b9a9d3e64abb240cdeb4050be37464..1682da69a657aaef184a3577d727054cfddc348a 100644 (file)
@@ -8,24 +8,36 @@
 package org.opendaylight.openflowplugin.applications.statistics.manager.impl.helper;
 
 import com.google.common.net.InetAddresses;
+import java.math.BigInteger;
 import java.net.Inet4Address;
-
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.primitives.UnsignedBytes;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
 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._3.match.Ipv4MatchArbitraryBitMask;
 
 /**
  * @author joe
+ * @author sai.marapareddy@gmail.com
  *
  */
 public class MatchComparatorHelper {
 
+    private static final Logger LOG = LoggerFactory.getLogger(MatchComparatorHelper.class);
     private static final int DEFAULT_SUBNET = 32;
     private static final int IPV4_MASK_LENGTH = 32;
     private static final int SHIFT_OCTET_1 = 24;
@@ -36,6 +48,9 @@ public class MatchComparatorHelper {
     private static final int POSITION_OCTET_2 = 1;
     private static final int POSITION_OCTET_3 = 2;
     private static final int POSITION_OCTET_4 = 3;
+    private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255";
+    private static final String PREFIX_SEPARATOR = "/";
+    private static final int IPV4_ADDRESS_LENGTH = 32;
 
     /*
      * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case
@@ -117,7 +132,81 @@ public class MatchComparatorHelper {
                 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(statsIpv6Match.getIpv6Source(),
                         storedIpv6Match.getIpv6Source());
             }
-        }else {
+        } else if(statsLayer3Match instanceof  Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) {
+            // At this moment storedIpv4MatchArbitraryBitMask & statsIpv4MatchArbitraryBitMask will always have non null arbitrary masks.
+            // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv4Match.
+            // Eg:- stats -> 1.0.1.0/255.0.255.0  stored -> 1.1.1.0/255.0.255.0
+            final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask= (Ipv4MatchArbitraryBitMask) statsLayer3Match;
+            final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match;
+            if((storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null |
+                    storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null)) {
+                if(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
+                        String storedIpAddress = extractIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
+                                storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
+                        if(MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue(),
+                                statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue())) {
+                            verdict = MatchComparatorHelper.compareStringNullSafe(storedIpAddress,
+                                    statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask().getValue());
+                        }
+                        else {
+                            verdict = false;
+                            return verdict;
+                        }
+                }
+                if(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
+                        String storedIpAddress = extractIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
+                                ,storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
+                        if(MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue(),
+                                statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue())) {
+                            verdict = MatchComparatorHelper.compareStringNullSafe(storedIpAddress,
+                                    statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask().getValue());
+                        }
+                        else {
+                            verdict = false;
+                        }
+                }
+            }
+            else {
+                final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
+                if (nullCheckOut != null) {
+                    verdict = nullCheckOut;
+                } else {
+                    verdict = storedLayer3Match.equals(statsLayer3Match);
+                }
+            }
+        }
+        else if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) {
+            // Here stored netmask is an instance of Ipv4MatchArbitraryBitMask, when it is pushed in to switch
+            // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
+            // Eg:- stats src/dest -> 1.1.1.0/24  stored src/dest -> 1.1.1.0/255.255.255.0
+            final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match;
+            final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match;
+            if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
+                Ipv4Prefix ipv4PrefixDestination;
+                if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) {
+                    byte[] destByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
+                    ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask);
+                }
+                else{
+                    ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask());
+                }
+                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, statsIpv4Match.getIpv4Destination());
+                if(verdict == false) {
+                    return verdict;
+                }
+            }
+            if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
+                Ipv4Prefix ipv4PrefixSource;
+                if (storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) {
+                    byte[] srcByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
+                    ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask);
+                }
+                else {
+                    ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask());
+                }
+                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source());
+            }
+        } else {
             final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
             if (nullCheckOut != null) {
                 verdict = nullCheckOut;
@@ -125,7 +214,6 @@ public class MatchComparatorHelper {
                 verdict = storedLayer3Match.equals(statsLayer3Match);
             }
         }
-
         return verdict;
     }
 
@@ -195,7 +283,17 @@ public class MatchComparatorHelper {
         } else if (!IpAddressEquals(statsIpv4, storedIpv4)) {
             verdict = false;
         }
+        return verdict;
+    }
 
+    static boolean compareStringNullSafe(final String stringA, final String stringB) {
+        boolean verdict = true;
+        final Boolean checkDestNullValuesOut = checkNullValues(stringA,stringB);
+        if (checkDestNullValuesOut != null) {
+            verdict = checkDestNullValuesOut;
+        }else if (!stringA.equals(stringB)) {
+            verdict = false;
+        }
         return verdict;
     }
 
@@ -251,4 +349,100 @@ public class MatchComparatorHelper {
         return integerIpAddress;
     }
 
+    static boolean isArbitraryBitMask(byte[] byteMask) {
+        if (byteMask == null) {
+            return false;
+        }
+        else {
+            ArrayList<Integer> integerMaskArrayList = new ArrayList<Integer>();
+            String maskInBits;
+            // converting byte array to bits
+            maskInBits = new BigInteger(1, byteMask).toString(2);
+            ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)")));
+            for(String string:stringMaskArrayList){
+                integerMaskArrayList.add(Integer.parseInt(string));
+            }
+            return checkArbitraryBitMask(integerMaskArrayList);
+        }
+    }
+
+    static boolean checkArbitraryBitMask(ArrayList<Integer> arrayList) {
+        // checks 0*1* case - Leading zeros in arrayList are truncated
+        if(arrayList.size()>0 && arrayList.size()<32) {
+            return true;
+        }
+        //checks 1*0*1 case
+        else {
+            for(int i=0; i<arrayList.size()-1;i++) {
+                if(arrayList.get(i) ==0 && arrayList.get(i+1) == 1) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    static final byte[] convertArbitraryMaskToByteArray(DottedQuad mask) {
+        String maskValue;
+        if(mask.getValue() != null && mask != null){
+            maskValue  = mask.getValue();
+        }
+        else maskValue = DEFAULT_ARBITRARY_BIT_MASK;
+        InetAddress maskInIpFormat = null;
+        try {
+            maskInIpFormat = InetAddress.getByName(maskValue);
+        } catch (UnknownHostException e) {
+            LOG.error("Failed to recognize the host while converting mask ", e);
+        }
+        byte[] bytes = maskInIpFormat.getAddress();
+        return bytes;
+    }
+
+
+    static String extractIpv4Address(Ipv4Address ipAddress, DottedQuad netMask) {
+        String actualIpAddress="";
+        String[] netMaskParts = netMask.getValue().split("\\.");
+        String[] ipAddressParts = ipAddress.getValue().split("\\.");
+
+        for(int i=0; i<ipAddressParts.length;i++) {
+            int integerFormatIpAddress=Integer.parseInt(ipAddressParts[i]);
+            int integerFormatNetMask=Integer.parseInt(netMaskParts[i]);
+            int ipAddressPart=(integerFormatIpAddress) & (integerFormatNetMask);
+            actualIpAddress += ipAddressPart;
+            if(i != ipAddressParts.length -1 ) {
+                actualIpAddress = actualIpAddress+".";
+            }
+        }
+        return actualIpAddress;
+    }
+
+    static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final byte [] bytemask){
+        return createPrefix(ipv4Address, String.valueOf(countBits(bytemask)));
+    }
+
+    static int countBits(final byte[] mask) {
+        int netmask = 0;
+        for (byte b : mask) {
+            netmask += Integer.bitCount(UnsignedBytes.toInt(b));
+        }
+        return netmask;
+    }
+
+    static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address){
+        return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);
+    }
+
+    static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final String mask){
+        /*
+         * Ipv4Address has already validated the address part of the prefix,
+         * It is mandated to comply to the same regexp as the address
+         * There is absolutely no point rerunning additional checks vs this
+         * Note - there is no canonical form check here!!!
+         */
+        if (null != mask && !mask.isEmpty()) {
+            return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + mask);
+        } else {
+            return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);
+        }
+    }
 }
index 772e3834c60a56ad7aa958bd8334659f6edcef1f..1fdb42c6909f4e37d3049aff5905d372247c9764 100644 (file)
@@ -4,8 +4,11 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMaskBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 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.l2.types.rev130827.EtherType;
@@ -16,6 +19,10 @@ 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.EthernetMatchBuilder;
 import org.junit.Test;
 
+/**
+ * @author sai.marapareddy@gmail.com (arbitrary masks)
+ */
+
 /**
  * test of {@link MatchComparatorHelper}
  */
@@ -161,6 +168,13 @@ public class MatchComparatorHelperTest {
                 new Ipv4Prefix("191.168.1.1/31")));
     }
 
+    @Test
+    public void compareStringNullSafeTest() {
+        assertEquals(true, MatchComparatorHelper.compareStringNullSafe(null,null));
+        assertEquals(true, MatchComparatorHelper.compareStringNullSafe("Hello", "Hello"));
+        assertEquals(false, MatchComparatorHelper.compareStringNullSafe("Hello", "hello"));
+    }
+
     private static final int ip_192_168_1_1 = 0xC0A80101;
     private static final int ip_192_168_1_4 = 0xC0A80104;
 
@@ -186,15 +200,119 @@ public class MatchComparatorHelperTest {
     public void layer3MatchEqualsTest() {
         final Ipv4MatchBuilder statsBuilder = new Ipv4MatchBuilder();
         final Ipv4MatchBuilder storedBuilder = new Ipv4MatchBuilder();
-
         assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
         statsBuilder.setIpv4Destination(new Ipv4Prefix("192.168.1.1/30"));
         storedBuilder.setIpv4Destination(new Ipv4Prefix("191.168.1.1/30"));
         assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
         assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
         assertEquals(true,
                 MatchComparatorHelper.layer3MatchEquals(new ArpMatchBuilder().build(), new ArpMatchBuilder().build()));
     }
+
+    @Test
+    public void layer3MatchEqualsIpv4ArbitraryMaskTest(){
+        final Ipv4MatchBuilder statsBuilder = new Ipv4MatchBuilder();
+        final Ipv4MatchArbitraryBitMaskBuilder storedBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
+        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
+        statsBuilder.setIpv4Destination(new Ipv4Prefix("192.168.1.1/24"));
+        storedBuilder.setIpv4DestinationAddressNoMask(new Ipv4Address("192.168.1.1"));
+        storedBuilder.setIpv4DestinationArbitraryBitmask(new DottedQuad("255.255.255.0"));
+        statsBuilder.setIpv4Source(new Ipv4Prefix("192.168.1.1/24"));
+        storedBuilder.setIpv4SourceAddressNoMask(new Ipv4Address("192.168.1.1"));
+        storedBuilder.setIpv4SourceArbitraryBitmask(new DottedQuad("255.255.255.0"));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
+
+    }
+
+    @Test
+    public void layer3MatchEqualsIpv4ArbitraryMaskRandomTest() {
+        final Ipv4MatchArbitraryBitMaskBuilder statsBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
+        final Ipv4MatchArbitraryBitMaskBuilder storedBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
+        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
+        statsBuilder.setIpv4DestinationAddressNoMask(new Ipv4Address("192.168.0.1"));
+        statsBuilder.setIpv4DestinationArbitraryBitmask(new DottedQuad("255.255.0.255"));
+        storedBuilder.setIpv4DestinationAddressNoMask(new Ipv4Address("192.168.1.1"));
+        storedBuilder.setIpv4DestinationArbitraryBitmask(new DottedQuad("255.255.0.255"));
+        statsBuilder.setIpv4SourceAddressNoMask(new Ipv4Address("192.0.0.1"));
+        statsBuilder.setIpv4SourceArbitraryBitmask(new DottedQuad("255.0.0.255"));
+        storedBuilder.setIpv4SourceAddressNoMask(new Ipv4Address("192.7.1.1"));
+        storedBuilder.setIpv4SourceArbitraryBitmask(new DottedQuad("255.0.0.255"));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
+    }
+
+    @Test
+    public void layer3MatchEqualsIpv4ArbitraryMaskEqualsNullTest() {
+        final Ipv4MatchBuilder statsBuilder = new Ipv4MatchBuilder();
+        final Ipv4MatchArbitraryBitMaskBuilder storedBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
+        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
+        statsBuilder.setIpv4Source(new Ipv4Prefix("192.168.0.1/32"));
+        storedBuilder.setIpv4DestinationAddressNoMask(new Ipv4Address("192.168.0.1"));
+        statsBuilder.setIpv4Destination(new Ipv4Prefix("192.1.0.0/32"));
+        storedBuilder.setIpv4SourceAddressNoMask(new Ipv4Address("192.1.0.0"));
+        assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
+    }
+
+    @Test
+    public void layer3MatchEqualsIpv4ArbitraryEmptyBitMaskTest(){
+        final Ipv4MatchBuilder statsBuilder = new Ipv4MatchBuilder();
+        final Ipv4MatchArbitraryBitMaskBuilder storedBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
+        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
+        statsBuilder.setIpv4Destination(new Ipv4Prefix("192.168.1.1/32"));
+        storedBuilder.setIpv4DestinationAddressNoMask(new Ipv4Address("192.168.1.1"));
+        statsBuilder.setIpv4Source(new Ipv4Prefix("192.168.1.1/32"));
+        storedBuilder.setIpv4SourceAddressNoMask(new Ipv4Address("192.168.1.1"));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
+        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
+    }
+
+    @Test
+    public void extractIpv4AddressTest() {
+        Ipv4Address ipAddress = new Ipv4Address("1.1.1.1");
+        DottedQuad netMask = new DottedQuad("255.255.255.0");
+        String extractedIpAddress;
+        extractedIpAddress = MatchComparatorHelper.extractIpv4Address(ipAddress,netMask);
+        assertEquals(extractedIpAddress,"1.1.1.0");
+    }
+
+    @Test
+    public void convertArbitraryMaskToByteArrayTest() {
+        int value = 0xffffffff;
+        byte[] bytes = new byte[]{
+                (byte)(value >>> 24), (byte)(value >> 16 & 0xff), (byte)(value >> 8 & 0xff), (byte)(value & 0xff) };
+        byte[] maskBytes;
+        maskBytes = MatchComparatorHelper.convertArbitraryMaskToByteArray(new DottedQuad("255.255.255.255"));
+        for(int i=0; i<bytes.length;i++){
+            int mask = maskBytes[i];
+            assertEquals(bytes[i],mask);
+        }
+    }
+
+    @Test
+    public void isArbitraryBitMaskTest() {
+        boolean arbitraryBitMask;
+        arbitraryBitMask = MatchComparatorHelper.isArbitraryBitMask(new byte[] {1,1,1,1});
+        assertEquals(arbitraryBitMask,true);
+        arbitraryBitMask = MatchComparatorHelper.isArbitraryBitMask(new byte[] {-1,-1,-1,-1});
+        assertEquals(arbitraryBitMask,false);
+        arbitraryBitMask = MatchComparatorHelper.isArbitraryBitMask(new byte[] {-1,-1,0,-1});
+        assertEquals(arbitraryBitMask,true);
+        arbitraryBitMask = MatchComparatorHelper.isArbitraryBitMask(null);
+        assertEquals(arbitraryBitMask,false);
+    }
+
+    @Test
+    public void createPrefixTest() {
+        Ipv4Address ipv4Address = new Ipv4Address("1.1.1.1");
+        byte [] byteMask = new byte[] {-1,-1,-1,-1};
+        Ipv4Prefix ipv4Prefix = MatchComparatorHelper.createPrefix(ipv4Address,byteMask);
+        assertEquals(ipv4Prefix,new Ipv4Prefix("1.1.1.1/32"));
+        String nullMask = "";
+        Ipv4Prefix ipv4PrefixNullMask = MatchComparatorHelper.createPrefix(ipv4Address,nullMask);
+        assertEquals(ipv4PrefixNullMask,new Ipv4Prefix("1.1.1.1/32"));
+        Ipv4Prefix ipv4PrefixNoMask = MatchComparatorHelper.createPrefix(ipv4Address);
+        assertEquals(ipv4PrefixNoMask,new Ipv4Prefix("1.1.1.1/32"));
+    }
 }
diff --git a/model/model-flow-base/src/main/yang/opendaylight-arbitrary-bitmask-fields.yang b/model/model-flow-base/src/main/yang/opendaylight-arbitrary-bitmask-fields.yang
new file mode 100644 (file)
index 0000000..ff194de
--- /dev/null
@@ -0,0 +1,34 @@
+module opendaylight-arbitrary-bitmask-fields {
+    namespace "urn:opendaylight:arbitrary:bitmask:fields";
+    prefix "mask";
+
+    import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
+    import ietf-yang-types {prefix yang; revision-date "2013-07-15";}
+
+    revision "2016-01-30" {
+        description "Initial revision of match types";
+    }
+
+    grouping "ipv4-match-arbitrary-bitmask-fields" {
+
+        leaf ipv4-source-address-no-mask {
+            description "IPv4 source address with no mask .";
+            type inet:ipv4-address;
+        }
+
+        leaf ipv4-destination-address-no-mask {
+            description "IPv4 destination address with no mask.";
+            type inet:ipv4-address;
+        }
+
+        leaf ipv4-source-arbitrary-bitmask {
+            description "IPv4 source address with no mask .";
+            type yang:dotted-quad;
+        }
+
+        leaf ipv4-destination-arbitrary-bitmask {
+            description "IPv4 destination address with no mask.";
+            type yang:dotted-quad;
+        }
+    }
+}
index deff6f17984cce55c8bcf97b43159f42852ebfec..332f27e613ea696f08d2f9981e52817c6f4418bb 100644 (file)
@@ -6,6 +6,7 @@ module opendaylight-match-types {
     import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
     import opendaylight-l2-types {prefix l2t;revision-date "2013-08-27";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+    import opendaylight-arbitrary-bitmask-fields {prefix mask; revision-date "2016-01-30";}
 
     revision "2013-10-26" {
         description "Initial revision of match types";
@@ -326,6 +327,9 @@ module opendaylight-match-types {
             case "ipv4-match" {
                 uses "ipv4-match-fields";
             }
+            case "ipv4-match-arbitrary-bit-mask"{
+                uses "mask:ipv4-match-arbitrary-bitmask-fields";
+            }
             case "ipv6-match" {
                 uses "ipv6-match-fields";
             }
index 3c746bf4885c39bdbb24e1867fc142ba69ee8e4d..a1dce132b4b9b18ef015c66d25960a8bc2df7e83 100644 (file)
       <groupId>org.opendaylight.mdsal.model</groupId>
       <artifactId>ietf-yang-types</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.mdsal.model</groupId>
       <artifactId>yang-ext</artifactId>
index 3ea654fe22364c722947a7f8c553f3f45b9f1380..61480de5f0f91aabee7f0171a976a626d8860933 100644 (file)
@@ -34,21 +34,21 @@ public class HandshakeListenerImpl implements HandshakeListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(HandshakeListenerImpl.class);
 
-    private ConnectionContext connectionContext;
-    private DeviceConnectedHandler deviceConnectedHandler;
+    private final ConnectionContext connectionContext;
+    private final DeviceConnectedHandler deviceConnectedHandler;
     private HandshakeContext handshakeContext;
 
     /**
      * @param connectionContext
      * @param deviceConnectedHandler
      */
-    public HandshakeListenerImpl(ConnectionContext connectionContext, DeviceConnectedHandler deviceConnectedHandler) {
+    public HandshakeListenerImpl(final ConnectionContext connectionContext, final DeviceConnectedHandler deviceConnectedHandler) {
         this.connectionContext = connectionContext;
         this.deviceConnectedHandler = deviceConnectedHandler;
     }
 
     @Override
-    public void onHandshakeSuccessfull(GetFeaturesOutput featureOutput, Short version) {
+    public void onHandshakeSuccessfull(final GetFeaturesOutput featureOutput, final Short version) {
         LOG.debug("handshake succeeded: {}", connectionContext.getConnectionAdapter().getRemoteAddress());
         closeHandshakeContext();
         connectionContext.changeStateToWorking();
@@ -65,11 +65,11 @@ public class HandshakeListenerImpl implements HandshakeListener {
                     deviceConnectedHandler.deviceConnected(connectionContext);
                     SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
                             SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
-                } catch (Exception e) {
+                } catch (final Exception e) {
                     LOG.info("ConnectionContext initial processing failed: {}", e.getMessage());
                     SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
                             SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
-                    connectionContext.closeConnection(false);
+                    connectionContext.closeConnection(true);
                 }
             }
 
@@ -100,14 +100,14 @@ public class HandshakeListenerImpl implements HandshakeListener {
     private void closeHandshakeContext() {
         try {
             handshakeContext.close();
-        } catch (Exception e) {
+        } catch (final Exception e) {
             LOG.warn("Closing handshake context failed: {}", e.getMessage());
             LOG.debug("Detail in hanshake context close:", e);
         }
     }
 
     @Override
-    public void setHandshakeContext(HandshakeContext handshakeContext) {
+    public void setHandshakeContext(final HandshakeContext handshakeContext) {
         this.handshakeContext = handshakeContext;
     }
 }
index 524e223f45622fab0d1b49984cf01fc0b05f61aa..e5c62d7e657a82bcfac6debb342a7f2d548fbc10 100644 (file)
@@ -14,6 +14,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.FutureFallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.util.HashedWheelTimer;
@@ -29,6 +30,8 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
@@ -244,6 +247,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             return Futures.immediateFuture(null);
         }
         if (OfpRole.BECOMEMASTER.equals(role)) {
+            MdSalRegistratorUtils.registerMasterServices(getRpcContext(), DeviceContextImpl.this, role);
+            getRpcContext().registerStatCompatibilityServices();
             if (!deviceState.deviceSynchronized()) {
                 //TODO: no necessary code for yet - it needs for initialization phase only
                 LOG.debug("Setup Empty TxManager {} for initialization phase", getDeviceState().getNodeId());
@@ -251,7 +256,23 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
                 return Futures.immediateCheckedFuture(null);
             }
             /* Relevant for no initial Slave-to-Master scenario in cluster */
-            return asyncClusterRoleChange(role);
+            final ListenableFuture<Void> deviceInitialization = asyncClusterRoleChange();
+            Futures.addCallback(deviceInitialization, new FutureCallback<Void>() {
+
+                @Override
+                public void onSuccess(@Nullable Void aVoid) {
+                    //No operation
+                }
+
+                @Override
+                public void onFailure(Throwable throwable) {
+                    LOG.debug("Device {} init unexpected fail. Unregister RPCs", getDeviceState().getNodeId());
+                    MdSalRegistratorUtils.unregisterServices(getRpcContext());
+                }
+
+            });
+
+            return deviceInitialization;
 
         } else if (OfpRole.BECOMESLAVE.equals(role)) {
             if (null != rpcContext) {
@@ -272,14 +293,14 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
      * check all NodeInformation for statistics otherwise statistics will not contains
      * all possible MultipartTypes for polling in StatTypeList
      */
-    private ListenableFuture<Void> asyncClusterRoleChange(final OfpRole role) {
+    private ListenableFuture<Void> asyncClusterRoleChange() {
         if (statCtx == null) {
-            final String errMsg = String.format("DeviceCtx {} is up but we are missing StatisticsContext", deviceState.getNodeId());
+            final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", deviceState.getNodeId());
             LOG.warn(errMsg);
             return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
         }
         if (rpcContext == null) {
-            final String errMsg = String.format("DeviceCtx {} is up but we are missing RpcContext", deviceState.getNodeId());
+            final String errMsg = String.format("DeviceCtx %s is up but we are missing RpcContext", deviceState.getNodeId());
             LOG.warn(errMsg);
             return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
         }
@@ -322,14 +343,14 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             @Override
             public Void apply(final Boolean input) {
                 if (ConnectionContext.CONNECTION_STATE.RIP.equals(getPrimaryConnectionContext().getConnectionState())) {
-                    final String errMsg = String.format("We lost connection for Device {}, context has to be closed.",
+                    final String errMsg = String.format("We lost connection for Device %s, context has to be closed.",
                             getDeviceState().getNodeId());
                     LOG.warn(errMsg);
                     transactionChainManager.clearUnsubmittedTransaction();
                     throw new IllegalStateException(errMsg);
                 }
                 if (!input.booleanValue()) {
-                    final String errMsg = String.format("Get Initial Device {} information fails",
+                    final String errMsg = String.format("Get Initial Device %s information fails",
                             getDeviceState().getNodeId());
                     LOG.warn(errMsg);
                     transactionChainManager.clearUnsubmittedTransaction();
@@ -338,8 +359,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
                 LOG.debug("Get Initial Device {} information is successful", getDeviceState().getNodeId());
                 getDeviceState().setDeviceSynchronized(true);
                 transactionChainManager.activateTransactionManager();
-                MdSalRegistratorUtils.registerMasterServices(getRpcContext(), DeviceContextImpl.this, role);
-                getRpcContext().registerStatCompatibilityServices();
                 initialSubmitTransaction();
                 getDeviceState().setStatisticsPollingEnabledProp(true);
                 return null;
@@ -542,14 +561,15 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     }
 
     @Override
-    public void close() {
+    public synchronized void close() {
         LOG.debug("closing deviceContext: {}, nodeId:{}",
                 getPrimaryConnectionContext().getConnectionAdapter().getRemoteAddress(),
                 getDeviceState().getNodeId());
 
-        tearDown();
-
-        primaryConnectionContext.closeConnection(false);
+        if (deviceState.isValid()) {
+            primaryConnectionContext.closeConnection(false);
+            tearDown();
+        }
     }
 
     private synchronized void tearDown() {
@@ -583,9 +603,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         }
     }
 
-    protected void tearDownClean() {
+    private void tearDownClean() {
         LOG.info("Closing transaction chain manager without cleaning inventory operational");
-        Preconditions.checkState(!deviceState.isValid());
         transactionChainManager.close();
 
         final LinkedList<DeviceContextClosedHandler> reversedCloseHandlers = new LinkedList<>(closeHandlers);
index 6b7d45f7f3a1b20fec90ebaf16ab1167acece5b1..15310237119be2b8c7bdb461f7893113e8fb13f8 100644 (file)
@@ -53,6 +53,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.Sal
 
 public class MdSalRegistratorUtils {
 
+    //TODO: Make one register and one unregister method for all services
+
     private static final TypeToken<Delegator<OpendaylightFlowStatisticsService>> COMPOSITE_SERVICE_TYPE_TOKEN =
             new TypeToken<Delegator<OpendaylightFlowStatisticsService>>() {
                 //NOBODY
index 7be1d00e1610a038baa1b1fc4743f0e357eca288..63cdfceb0542d89883356daa198c9265b2911b92 100644 (file)
@@ -395,10 +395,9 @@ public class DeviceContextImplTest {
         deviceContext.addAuxiliaryConenctionContext(mockedAuxiliaryConnectionContext);
         DeviceContextClosedHandler mockedDeviceContextClosedHandler = mock(DeviceContextClosedHandler.class);
         deviceContext.addDeviceContextClosedHandler(mockedDeviceContextClosedHandler);
+        when(deviceState.isValid()).thenReturn(true);
         deviceContext.close();
-        verify(connectionContext).closeConnection(eq(false));
-//        verify(deviceState).setValid(eq(false));
-//        verify(mockedAuxiliaryConnectionContext).closeConnection(eq(false));
+        verify(connectionContext).closeConnection(false);
     }
 
     @Test
index 1f125ef7744e6e7b926df0d5e002b96c29c80e41..5151d300c8ba8d8428e5fd8976810079af9e5a91 100644 (file)
@@ -8,30 +8,37 @@
 
 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterators;
-import com.google.common.net.InetAddresses;
-import com.google.common.primitives.UnsignedBytes;
+import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterators;
+import com.google.common.net.InetAddresses;
+import com.google.common.primitives.UnsignedBytes;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
 
 
 /**
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 5.3.2015.
  * v6 routines added by Anton Ivanov on 14.6.2015
+ * Arbitrary masks by sai.marapareddy@gmail.com
  */
 public final class IpConversionUtil {
 
+    private static final Logger LOG = LoggerFactory.getLogger(IpConversionUtil.class);
     public static final String PREFIX_SEPARATOR = "/";
     public static final Splitter PREFIX_SPLITTER = Splitter.on('/');
     private static final int INADDR4SZ = 4;
@@ -39,6 +46,7 @@ public final class IpConversionUtil {
     private static final int INT16SZ = 2;
     private static final int IPV4_ADDRESS_LENGTH = 32;
     private static final int IPV6_ADDRESS_LENGTH = 128;
+    private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255";
 
     /*
      * Prefix bytearray lookup table. We concatenate the prefixes
@@ -120,6 +128,16 @@ public final class IpConversionUtil {
         return IetfInetUtil.INSTANCE.ipv4PrefixFor(ipv4Address, countBits(bytemask));
     }
 
+    public static DottedQuad createArbitraryBitMask(final byte [] bytemask)  {
+        DottedQuad dottedQuad = new DottedQuad(DEFAULT_ARBITRARY_BIT_MASK);
+        try {
+            dottedQuad = new DottedQuad(InetAddress.getByAddress(bytemask).getHostAddress());
+        } catch (UnknownHostException e) {
+            LOG.error("Failed to create the dottedQuad notation for the given mask ", e);
+        }
+        return dottedQuad;
+    }
+
     public static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address){
         return IetfInetUtil.INSTANCE.ipv6PrefixFor(ipv6Address);
     }
@@ -577,4 +595,55 @@ public final class IpConversionUtil {
         }
         return netmask;
     }
+
+    public static final byte[] convertArbitraryMaskToByteArray(DottedQuad mask) {
+        String maskValue;
+        if (mask != null && mask.getValue() != null){
+           maskValue  = mask.getValue();
+        }
+        else {
+            maskValue = DEFAULT_ARBITRARY_BIT_MASK;
+        }
+        InetAddress maskInIpFormat = null;
+        try {
+            maskInIpFormat = InetAddress.getByName(maskValue);
+        } catch (UnknownHostException e) {
+            LOG.error ("Failed to resolve the ip address of the mask",e);
+        }
+        byte[] bytes = maskInIpFormat.getAddress();
+        return bytes;
+    }
+
+    public static boolean isArbitraryBitMask(byte[] byteMask) {
+        if (byteMask == null) {
+            return false;
+        }
+        else {
+            ArrayList<Integer> integerMaskArrayList = new ArrayList<Integer>();
+            String maskInBits;
+            // converting byte array to bits
+            maskInBits = new BigInteger(1, byteMask).toString(2);
+            ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)")));
+            for(String string:stringMaskArrayList){
+                integerMaskArrayList.add(Integer.parseInt(string));
+            }
+            return checkArbitraryBitMask(integerMaskArrayList);
+        }
+    }
+
+    private static boolean checkArbitraryBitMask(ArrayList<Integer> arrayList) {
+        // checks 0*1* case - Leading zeros in arrayList are truncated
+        if(arrayList.size()>0 && arrayList.size()<32) {
+            return true;
+        }
+        //checks 1*0*1 case
+        else {
+            for(int i=0; i<arrayList.size()-1;i++) {
+                if(arrayList.get(i) ==0 && arrayList.get(i+1) == 1) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
index 68b050a50b4a567c3528f351062d524857881d18..a78f48968b8844b17180c0219bc51f80edfc1f1a 100644 (file)
@@ -35,6 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6FlowLabel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
@@ -68,14 +69,7 @@ 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.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
-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.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._3.match.TunnelIpv4Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
@@ -388,7 +382,58 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
 
     private static void layer3Match(final List<MatchEntry> matchEntryList, final Layer3Match layer3Match) {
         if (layer3Match != null) {
-            if (layer3Match instanceof Ipv4Match) {
+            if(layer3Match instanceof Ipv4MatchArbitraryBitMask) {
+                Ipv4MatchArbitraryBitMask ipv4MatchArbitraryBitMaskFields = (Ipv4MatchArbitraryBitMask) layer3Match;
+                if (ipv4MatchArbitraryBitMaskFields.getIpv4SourceAddressNoMask() != null) {
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv4Src.class);
+
+                    Ipv4SrcCaseBuilder ipv4SrcCaseBuilder = new Ipv4SrcCaseBuilder();
+                    Ipv4SrcBuilder ipv4SrcBuilder = new Ipv4SrcBuilder();
+
+                    ipv4SrcBuilder.setIpv4Address(ipv4MatchArbitraryBitMaskFields.getIpv4SourceAddressNoMask());
+                    DottedQuad sourceArbitrarySubNetMask = ipv4MatchArbitraryBitMaskFields.getIpv4SourceArbitraryBitmask();
+
+                    boolean hasMask = false;
+                    if (sourceArbitrarySubNetMask != null) {
+                        byte[] maskByteArray = IpConversionUtil.convertArbitraryMaskToByteArray(sourceArbitrarySubNetMask);
+                        if (maskByteArray != null) {
+                            ipv4SrcBuilder.setMask(maskByteArray);
+                            hasMask = true;
+                        }
+                    }
+                    matchEntryBuilder.setHasMask(hasMask);
+                    ipv4SrcCaseBuilder.setIpv4Src(ipv4SrcBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(ipv4SrcCaseBuilder.build());
+                    matchEntryList.add(matchEntryBuilder.build());
+                }
+                if (ipv4MatchArbitraryBitMaskFields.getIpv4DestinationAddressNoMask() != null) {
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv4Dst.class);
+
+                    Ipv4DstCaseBuilder ipv4DstCaseBuilder = new Ipv4DstCaseBuilder();
+                    Ipv4DstBuilder ipv4DstBuilder = new Ipv4DstBuilder();
+
+                    ipv4DstBuilder.setIpv4Address(ipv4MatchArbitraryBitMaskFields.getIpv4DestinationAddressNoMask());
+                    DottedQuad destArbitrarySubNetMask = ipv4MatchArbitraryBitMaskFields.getIpv4DestinationArbitraryBitmask();
+
+                    boolean hasMask = false;
+                    if (destArbitrarySubNetMask != null) {
+                        byte[] maskByteArray = IpConversionUtil.convertArbitraryMaskToByteArray(destArbitrarySubNetMask);
+                        if (maskByteArray != null) {
+                            ipv4DstBuilder.setMask(maskByteArray);
+                            hasMask = true;
+                        }
+                    }
+                    matchEntryBuilder.setHasMask(hasMask);
+                    ipv4DstCaseBuilder.setIpv4Dst(ipv4DstBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(ipv4DstCaseBuilder.build());
+                    matchEntryList.add(matchEntryBuilder.build());
+                }
+            }
+            if(layer3Match instanceof Ipv4Match){
                 Ipv4Match ipv4Match = (Ipv4Match) layer3Match;
                 if (ipv4Match.getIpv4Source() != null) {
                     Ipv4Prefix ipv4Prefix = ipv4Match.getIpv4Source();
@@ -1099,6 +1144,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         Icmpv4MatchBuilder icmpv4MatchBuilder = new Icmpv4MatchBuilder();
         Icmpv6MatchBuilder icmpv6MatchBuilder = new Icmpv6MatchBuilder();
         Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder();
+        Ipv4MatchArbitraryBitMaskBuilder ipv4MatchArbitraryBitMaskBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
         ArpMatchBuilder arpMatchBuilder = new ArpMatchBuilder();
         Ipv6MatchBuilder ipv6MatchBuilder = new Ipv6MatchBuilder();
         ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = new ProtocolMatchFieldsBuilder();
@@ -1270,17 +1316,33 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ipv4.src._case.Ipv4Src ipv4Address = ((Ipv4SrcCase) ofMatch.getMatchEntryValue()).getIpv4Src();
                 if (ipv4Address != null) {
                     byte[] mask = ipv4Address.getMask();
-                    String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
-                    setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
-                    matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    if (mask != null && IpConversionUtil.isArbitraryBitMask(mask)) {
+                        DottedQuad dottedQuadMask = IpConversionUtil.createArbitraryBitMask(mask);
+                        String Ipv4Address = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchArbitraryBitMaskBuilderFields(ipv4MatchArbitraryBitMaskBuilder, ofMatch, dottedQuadMask, Ipv4Address);
+                        matchBuilder.setLayer3Match(ipv4MatchArbitraryBitMaskBuilder.build());
+                    }
+                    else {
+                        String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
+                        matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    }
                 }
             } else if (ofMatch.getOxmMatchField().equals(Ipv4Dst.class)) {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ipv4.dst._case.Ipv4Dst ipv4Address = ((Ipv4DstCase) ofMatch.getMatchEntryValue()).getIpv4Dst();
                 if (ipv4Address != null) {
                     byte[] mask = ipv4Address.getMask();
-                    String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
-                    setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
-                    matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    if(mask != null && IpConversionUtil.isArbitraryBitMask(mask)) {
+                        DottedQuad dottedQuadMask = IpConversionUtil.createArbitraryBitMask(mask);
+                        String Ipv4Address = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchArbitraryBitMaskBuilderFields(ipv4MatchArbitraryBitMaskBuilder, ofMatch, dottedQuadMask, Ipv4Address);
+                        matchBuilder.setLayer3Match(ipv4MatchArbitraryBitMaskBuilder.build());
+                    }
+                    else {
+                        String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
+                        matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    }
                 }
             } else if (ofMatch.getOxmMatchField().equals(TunnelIpv4Dst.class)
                     || ofMatch.getOxmMatchField().equals(TunnelIpv4Src.class)) {
@@ -1510,6 +1572,27 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         }
     }
 
+    private static void setIpv4MatchArbitraryBitMaskBuilderFields(final Ipv4MatchArbitraryBitMaskBuilder ipv4MatchArbitraryBitMaskBuilder, final MatchEntry ofMatch, final DottedQuad mask, final String ipv4AddressStr) {
+        Ipv4Address ipv4Address;
+        DottedQuad dottedQuad;
+        if (mask != null) {
+            dottedQuad = mask;
+            if (ofMatch.getOxmMatchField().equals(Ipv4Src.class)) {
+                ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceArbitraryBitmask(dottedQuad);
+            }
+            if (ofMatch.getOxmMatchField().equals(Ipv4Dst.class)) {
+                ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationArbitraryBitmask(dottedQuad);
+            }
+        }
+        ipv4Address = new Ipv4Address(ipv4AddressStr);
+        if (ofMatch.getOxmMatchField().equals(Ipv4Src.class)) {
+            ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceAddressNoMask(ipv4Address);
+        }
+        if (ofMatch.getOxmMatchField().equals(Ipv4Dst.class)) {
+            ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationAddressNoMask(ipv4Address);
+        }
+    }
+
 
     private static MatchEntry toOfMplsPbb(final Pbb pbb) {
         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
@@ -1840,5 +1923,4 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         return setField.build();
     }
 
-
 }
index e15854402f220fd1308a1c5b2889c05c65f4bb8d..c65fb40b366d6a2e54bdedb41147bafd577db8a7 100644 (file)
@@ -15,11 +15,13 @@ import org.opendaylight.openflowjava.util.ByteBufUtils;
 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchConvertorUtil;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
 /**\r
  * @author Anton Ivanov aivanov@brocade.com\r
+ * @author Sai MarapaReddy sai.marapareddy@gmail.com\r
  *\r
  */\r
 public class IpConversionUtilTest {\r
@@ -105,4 +107,30 @@ public class IpConversionUtilTest {
             Assert.assertEquals(maskOutputs[i], mask);\r
         }\r
     }\r
+\r
+    @Test\r
+    public void convertArbitraryMaskToByteArrayTest() {\r
+        int value = 0xffffffff;\r
+        byte[] bytes = new byte[]{\r
+                (byte)(value >>> 24), (byte)(value >> 16 & 0xff), (byte)(value >> 8 & 0xff), (byte)(value & 0xff) };\r
+        byte[] maskBytes;\r
+        maskBytes = IpConversionUtil.convertArbitraryMaskToByteArray(new DottedQuad("255.255.255.255"));\r
+        for(int i=0; i<bytes.length;i++){\r
+            int mask = maskBytes[i];\r
+            Assert.assertEquals(bytes[i],mask);\r
+        }\r
+    }\r
+\r
+    @Test\r
+    public void isArbitraryBitMaskTest() {\r
+        boolean arbitraryBitMask;\r
+        arbitraryBitMask = IpConversionUtil.isArbitraryBitMask(new byte[] {1,1,1,1});\r
+        Assert.assertEquals(arbitraryBitMask,true);\r
+        arbitraryBitMask = IpConversionUtil.isArbitraryBitMask(new byte[] {-1,-1,-1,-1});\r
+        Assert.assertEquals(arbitraryBitMask,false);\r
+        arbitraryBitMask = IpConversionUtil.isArbitraryBitMask(new byte[] {-1,-1,0,-1});\r
+        Assert.assertEquals(arbitraryBitMask,true);\r
+        arbitraryBitMask = IpConversionUtil.isArbitraryBitMask(null);\r
+        Assert.assertEquals(arbitraryBitMask,false);\r
+    }\r
 }\r
index d352b37990d7a1470fbda1714d01ddd10484df09..843f36738133f275c37c8d034e705f7a4a1b6d94 100644 (file)
@@ -12,13 +12,9 @@ import org.junit.Assert;
 import org.junit.Before;\r
 import org.junit.Test;\r
 import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6FlowLabel;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;\r
@@ -41,6 +37,7 @@ 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.TunnelBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMaskBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;\r
@@ -336,6 +333,54 @@ public class MatchConvertorImpl2Test {
         Assert.assertEquals("Wrong hasMask", hasMask, entry.isHasMask());\r
     }\r
 \r
+    /**\r
+     * Test {@link MatchConvertorImpl#convert(org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match, java.math.BigInteger)}\r
+     */\r
+    @Test\r
+    public void testIpv4MatchArbitraryBitMaskwithNoMask(){\r
+        MatchBuilder builder = new MatchBuilder();\r
+        Ipv4MatchArbitraryBitMaskBuilder ipv4MatchArbitraryBitMaskBuilder= new Ipv4MatchArbitraryBitMaskBuilder();\r
+        ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceAddressNoMask( new Ipv4Address("10.2.2.2"));\r
+        ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationAddressNoMask( new Ipv4Address("10.1.1.1"));\r
+        builder.setLayer3Match(ipv4MatchArbitraryBitMaskBuilder.build());\r
+        Match match = builder.build();\r
+\r
+        List<MatchEntry> entries = convertor.convert(match, new BigInteger("42"));\r
+        Assert.assertEquals("Wrong entries size", 2, entries.size());\r
+\r
+        MatchEntry entry = entries.get(0);\r
+        checkEntryHeader(entry,Ipv4Src.class,false);\r
+        Assert.assertEquals("wrong Ipv4Address source", "10.2.2.2",((Ipv4SrcCase) entry.getMatchEntryValue()).getIpv4Src().getIpv4Address().getValue());\r
+        entry = entries.get(1);\r
+        checkEntryHeader(entry,Ipv4Dst.class,false);\r
+        Assert.assertEquals("wrong Ipv4Address destination", "10.1.1.1",((Ipv4DstCase) entry.getMatchEntryValue()).getIpv4Dst().getIpv4Address().getValue());\r
+    }\r
+\r
+    /**\r
+     * Test {@link MatchConvertorImpl#convert(org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match, BigInteger)}\r
+     */\r
+    @Test\r
+    public void testIpv4MatchArbitraryBitMaskwithMask(){\r
+        MatchBuilder builder = new MatchBuilder();\r
+        Ipv4MatchArbitraryBitMaskBuilder ipv4MatchArbitraryBitMaskBuilder= new Ipv4MatchArbitraryBitMaskBuilder();\r
+        ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceAddressNoMask( new Ipv4Address("10.2.2.2"));\r
+        ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceArbitraryBitmask(new DottedQuad("0.0.255.0"));\r
+        ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationAddressNoMask( new Ipv4Address("10.1.1.1"));\r
+        ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationArbitraryBitmask(new DottedQuad("0.240.0.0"));\r
+        builder.setLayer3Match(ipv4MatchArbitraryBitMaskBuilder.build());\r
+        Match match = builder.build();\r
+\r
+        List<MatchEntry> entries = convertor.convert(match, new BigInteger("42"));\r
+        Assert.assertEquals("Wrong entries size", 2, entries.size());\r
+\r
+        MatchEntry entry = entries.get(0);\r
+        checkEntryHeader(entry,Ipv4Src.class,true);\r
+        Assert.assertEquals("wrong Ipv4Address source", "10.2.2.2",((Ipv4SrcCase) entry.getMatchEntryValue()).getIpv4Src().getIpv4Address().getValue());\r
+        entry = entries.get(1);\r
+        checkEntryHeader(entry,Ipv4Dst.class,true);\r
+        Assert.assertEquals("wrong Ipv4Adress destination", "10.1.1.1",((Ipv4DstCase) entry.getMatchEntryValue()).getIpv4Dst().getIpv4Address().getValue());\r
+    }\r
+\r
     /**\r
      * Test {@link MatchConvertorImpl#convert(org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match, java.math.BigInteger)}\r
      */\r
index f709c9be2f03d2a569bb990c8ee48a6921121057..e1e763a7762d21b7e54021256fb1d79e931d26d0 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;\r
@@ -659,6 +660,55 @@ public class MatchConvertorImplV13Test {
                 builtMatch.getTunnel().getTunnelId());\r
     }\r
 \r
+    /**\r
+     * Test {@link MatchConvertorImpl#fromOFMatchToSALMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match, java.math.BigInteger, org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion)}\r
+     */\r
+    @Test\r
+    public void testWithMatchEntryWithArbitraryMasks() {\r
+        final MatchBuilder builder = new MatchBuilder();\r
+        builder.setType(OxmMatchType.class);\r
+        final List<MatchEntry> entries = new ArrayList<>();\r
+        MatchEntryBuilder entriesBuilder = new MatchEntryBuilder();\r
+        entriesBuilder.setOxmClass(OpenflowBasicClass.class);\r
+        entriesBuilder.setOxmMatchField(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Metadata.class);\r
+        entriesBuilder.setHasMask(true);\r
+\r
+        entriesBuilder = new MatchEntryBuilder();\r
+        entriesBuilder.setOxmClass(OpenflowBasicClass.class);\r
+        entriesBuilder.setOxmMatchField(Ipv4Src.class);\r
+        entriesBuilder.setHasMask(true);\r
+        final Ipv4SrcCaseBuilder ipv4SrcCaseBuilder = new Ipv4SrcCaseBuilder();\r
+        final Ipv4SrcBuilder ipv4SrcBuilder = new Ipv4SrcBuilder();\r
+        ipv4SrcBuilder.setIpv4Address(new Ipv4Address("10.1.1.1"));\r
+        ipv4SrcBuilder.setMask(new byte[]{(byte) 255, 0, (byte) 255, 0});\r
+        ipv4SrcCaseBuilder.setIpv4Src(ipv4SrcBuilder.build());\r
+        entriesBuilder.setMatchEntryValue(ipv4SrcCaseBuilder.build());\r
+        entries.add(entriesBuilder.build());\r
+\r
+        entriesBuilder = new MatchEntryBuilder();\r
+        entriesBuilder.setOxmClass(OpenflowBasicClass.class);\r
+        entriesBuilder.setOxmMatchField(Ipv4Dst.class);\r
+        entriesBuilder.setHasMask(true);\r
+        final Ipv4DstCaseBuilder ipv4DstCaseBuilder = new Ipv4DstCaseBuilder();\r
+        final Ipv4DstBuilder ipv4AddressBuilder = new Ipv4DstBuilder();\r
+        ipv4AddressBuilder.setIpv4Address(new Ipv4Address("10.0.1.1"));\r
+        ipv4AddressBuilder.setMask(new byte[]{(byte) 255, 0, (byte) 240, 0});\r
+        ipv4DstCaseBuilder.setIpv4Dst(ipv4AddressBuilder.build());\r
+        entriesBuilder.setMatchEntryValue(ipv4DstCaseBuilder.build());\r
+        entries.add(entriesBuilder.build());\r
+\r
+        builder.setMatchEntry(entries);\r
+        final Match match = builder.build();\r
+\r
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow\r
+                .MatchBuilder salMatch = MatchConvertorImpl.fromOFMatchToSALMatch(match, new BigInteger("42"), OpenflowVersion.OF10);\r
+        final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match builtMatch = salMatch.build();\r
+\r
+        final Ipv4MatchArbitraryBitMask ipv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) builtMatch.getLayer3Match();\r
+        Assert.assertEquals("Wrong ipv4 src address", "10.1.1.1", ipv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask().getValue());\r
+        Assert.assertEquals("Wrong ipv4 dst address", "10.0.1.1", ipv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask().getValue());\r
+    }\r
+\r
     /**\r
      * Test {@link MatchConvertorImpl#fromOFMatchToSALMatch(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match, java.math.BigInteger, org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion)}\r
      */\r