Fix DeviceFlowRegistry performance regression 72/53972/16
authorTomas Slusny <tomas.slusny@pantheon.tech>
Tue, 28 Mar 2017 11:06:04 +0000 (13:06 +0200)
committerTomas Slusny <tomas.slusny@pantheon.tech>
Mon, 3 Apr 2017 10:50:00 +0000 (10:50 +0000)
- Remove use of marks and modify DeviceFlowRegistry immediately
- Synchronize only access to DeviceFlowRegistry BiMap and not
  entire class
- Replace custom match comparison with match normalization (should be a
lot faster on big amount of flows)
- When logging to console, compute FlowRegistryKey hashes only when needed

See also: bug 6917

Change-Id: I25e12a8254b75063e4fdc840eddd70386e3b0f26
Signed-off-by: Tomas Slusny <tomas.slusny@pantheon.tech>
20 files changed:
extension/openflowplugin-extension-api/src/main/java/org/opendaylight/openflowplugin/extension/api/GroupingLooseResolver.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/registry/CommonDeviceRegistry.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/registry/flow/DeviceFlowRegistry.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/datastore/multipart/FlowStatsMultipartWriter.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/flow/DeviceFlowRegistryImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/flow/FlowDescriptorFactory.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/flow/FlowRegistryKeyFactory.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/group/DeviceGroupRegistryImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/registry/meter/DeviceMeterRegistryImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/AddressNormalizationUtil.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/IntegerIpAddress.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorFactory.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorHelper.java [deleted file]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchNormalizationUtil.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/SimpleComparator.java [deleted file]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/registry/flow/DeviceFlowRegistryImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/registry/flow/FlowDescriptorDtoTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/AddressNormalizationUtilTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorHelperTest.java [deleted file]
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/common/IpConversionUtil.java

index 037715d34ea914f2bb3220f33d26c12da764b4c0..0d12c8f86d25e1febb9b206b600baa12ea5285b8 100644 (file)
@@ -38,6 +38,14 @@ public class GroupingLooseResolver<G> {
         classes = new HashSet<>();
     }
 
+    /**
+     * Get augmentation classes
+     * @return list of augmentation classes
+     */
+    public Set<Class<? extends Augmentation<?>>> getClasses() {
+        return classes;
+    }
+
     /**
      * @param cls equivalent augmentation class
      * @return this for chaining
@@ -67,4 +75,5 @@ public class GroupingLooseResolver<G> {
 
         return Optional.empty();
     }
+
 }
index afa1d0386db3eba62be3aed175fa082561f84e1b..a5c019dc6df4efaa326da9eae578f66f31f38319 100644 (file)
@@ -24,13 +24,6 @@ public interface CommonDeviceRegistry<KEY> extends AutoCloseable {
      */
     void addMark(KEY key);
 
-    /**
-     * Checks if registry has mark for KEY.
-     * @param key device registry key
-     * @return true if device registry has mark for KEY
-     */
-    boolean hasMark(KEY key);
-
     /**
      * Process marked keys.
      */
index d98f56b3f4cbf1a5b0ab033d31a2818a4ecb1d40..6dbd7094737a2431e916084732066000fc06cc1e 100644 (file)
@@ -12,7 +12,8 @@ package org.opendaylight.openflowplugin.api.openflow.registry.flow;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
-import java.util.function.BiConsumer;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.openflowplugin.api.openflow.registry.CommonDeviceRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 
@@ -24,10 +25,9 @@ public interface DeviceFlowRegistry extends CommonDeviceRegistry<FlowRegistryKey
 
     ListenableFuture<List<Optional<FlowCapableNode>>> fill();
 
-    void storeDescriptor(FlowRegistryKey flowRegistryKey, FlowDescriptor flowDescriptor);
+    void storeDescriptor(@Nonnull FlowRegistryKey flowRegistryKey, @Nonnull FlowDescriptor flowDescriptor);
 
-    FlowDescriptor retrieveDescriptor(FlowRegistryKey flowRegistryKey);
-
-    void forEachEntry(BiConsumer<FlowRegistryKey, FlowDescriptor> consumer);
+    @Nullable
+    FlowDescriptor retrieveDescriptor(@Nonnull FlowRegistryKey flowRegistryKey);
 
 }
index 46f00833d739960a77b3cc8880b81f1ac22306a8..528601939c5d8623ef841673885549dd6e905e4f 100644 (file)
@@ -8,8 +8,10 @@
 
 package org.opendaylight.openflowplugin.impl.datastore.multipart;
 
+import java.util.Objects;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
 import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -58,21 +60,25 @@ public class FlowStatsMultipartWriter extends AbstractMultipartWriter<FlowAndSta
                 final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(version, flow.build());
                 registry.getDeviceFlowRegistry().store(flowRegistryKey);
 
-                final FlowKey key = new FlowKey(registry
-                    .getDeviceFlowRegistry()
-                    .retrieveDescriptor(flowRegistryKey)
-                    .getFlowId());
+                final FlowDescriptor flowDescriptor = registry
+                        .getDeviceFlowRegistry()
+                        .retrieveDescriptor(flowRegistryKey);
 
-                writeToTransaction(
-                    getInstanceIdentifier()
-                        .augmentation(FlowCapableNode.class)
-                        .child(Table.class, new TableKey(stat.getTableId()))
-                        .child(Flow.class, key),
-                    flow
-                        .setId(key.getId())
-                        .setKey(key)
-                        .build(),
-                    withParents);
+                if (Objects.nonNull(flowDescriptor)) {
+                    final FlowKey key = new FlowKey(flowDescriptor
+                            .getFlowId());
+
+                    writeToTransaction(
+                            getInstanceIdentifier()
+                                    .augmentation(FlowCapableNode.class)
+                                    .child(Table.class, new TableKey(stat.getTableId()))
+                                    .child(Flow.class, key),
+                            flow
+                                    .setId(key.getId())
+                                    .setKey(key)
+                                    .build(),
+                            withParents);
+                }
             });
     }
 
index 9492b690fb96d6be39bfa54ff2580fbe96a3399a..5009323f93c76aa89aef1a84634578c7d5cdaa3b 100644 (file)
@@ -11,21 +11,20 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.BiConsumer;
 import java.util.function.Consumer;
-import javax.annotation.concurrent.GuardedBy;
+import javax.annotation.Nonnull;
 import javax.annotation.concurrent.ThreadSafe;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
@@ -50,8 +49,7 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
     private static final String ALIEN_SYSTEM_FLOW_ID = "#UF$TABLE*";
     private static final AtomicInteger UNACCOUNTED_FLOWS_COUNTER = new AtomicInteger(0);
 
-    private final BiMap<FlowRegistryKey, FlowDescriptor> flowRegistry = HashBiMap.create();
-    private final List<FlowRegistryKey> marks = new ArrayList<>();
+    private final BiMap<FlowRegistryKey, FlowDescriptor> flowRegistry = Maps.synchronizedBiMap(HashBiMap.create());
     private final DataBroker dataBroker;
     private final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier;
     private final List<ListenableFuture<List<Optional<FlowCapableNode>>>> lastFillFutures = new ArrayList<>();
@@ -61,24 +59,22 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
         this.dataBroker = dataBroker;
         this.instanceIdentifier = instanceIdentifier;
 
-        // Specifies what to do with flow read from datastore
+        // Specifies what to do with flow read from data store
         flowConsumer = flow -> {
-            // Create flow registry key from flow
-            final FlowRegistryKey key = FlowRegistryKeyFactory.create(version, flow);
-
-            // Now, we will update the registry, but we will also try to prevent duplicate entries
-            if (!flowRegistry.containsKey(key)) {
-                LOG.trace("Found flow with table ID : {} and flow ID : {}", flow.getTableId(), flow.getId().getValue());
-                final FlowDescriptor descriptor = FlowDescriptorFactory.create(flow.getTableId(), flow.getId());
-                storeDescriptor(key, descriptor);
+            final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(version, flow);
+
+            if (!flowRegistry.containsKey(flowRegistryKey)) {
+                // Now, we will update the registry
+                storeDescriptor(flowRegistryKey, FlowDescriptorFactory.create(flow.getTableId(), flow.getId()));
             }
         };
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized ListenableFuture<List<Optional<FlowCapableNode>>> fill() {
-        LOG.debug("Filling flow registry with flows for node: {}", instanceIdentifier.getKey().getId().getValue());
+    public ListenableFuture<List<Optional<FlowCapableNode>>> fill() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Filling flow registry with flows for node: {}", instanceIdentifier.getKey().getId().getValue());
+        }
 
         // Prepare path for read transaction
         // TODO: Read only Tables, and not entire FlowCapableNode (fix Yang model)
@@ -100,7 +96,6 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
         return lastFillFuture;
     }
 
-    @GuardedBy("this")
     private CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> fillFromDatastore(final LogicalDatastoreType logicalDatastoreType, final InstanceIdentifier<FlowCapableNode> path) {
         // Create new read-only transaction
         final ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
@@ -108,32 +103,32 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
         // Bail out early if transaction is null
         if (transaction == null) {
             return Futures.immediateFailedCheckedFuture(
-                new ReadFailedException("Read transaction is null"));
+                    new ReadFailedException("Read transaction is null"));
         }
 
         // Prepare read operation from datastore for path
         final CheckedFuture<Optional<FlowCapableNode>, ReadFailedException> future =
-            transaction.read(logicalDatastoreType, path);
+                transaction.read(logicalDatastoreType, path);
 
         // Bail out early if future is null
         if (future == null) {
             return Futures.immediateFailedCheckedFuture(
-                new ReadFailedException("Future from read transaction is null"));
+                    new ReadFailedException("Future from read transaction is null"));
         }
 
         Futures.addCallback(future, new FutureCallback<Optional<FlowCapableNode>>() {
             @Override
             public void onSuccess(Optional<FlowCapableNode> result) {
                 result.asSet().stream()
-                    .filter(Objects::nonNull)
-                    .filter(flowCapableNode -> Objects.nonNull(flowCapableNode.getTable()))
-                    .flatMap(flowCapableNode -> flowCapableNode.getTable().stream())
-                    .filter(Objects::nonNull)
-                    .filter(table -> Objects.nonNull(table.getFlow()))
-                    .flatMap(table -> table.getFlow().stream())
-                    .filter(Objects::nonNull)
-                    .filter(flow -> Objects.nonNull(flow.getId()))
-                    .forEach(flowConsumer);
+                        .filter(Objects::nonNull)
+                        .filter(flowCapableNode -> Objects.nonNull(flowCapableNode.getTable()))
+                        .flatMap(flowCapableNode -> flowCapableNode.getTable().stream())
+                        .filter(Objects::nonNull)
+                        .filter(table -> Objects.nonNull(table.getFlow()))
+                        .flatMap(table -> table.getFlow().stream())
+                        .filter(Objects::nonNull)
+                        .filter(flow -> Objects.nonNull(flow.getId()))
+                        .forEach(flowConsumer);
 
                 // After we are done with reading from datastore, close the transaction
                 transaction.close();
@@ -150,114 +145,88 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized FlowDescriptor retrieveDescriptor(final FlowRegistryKey flowRegistryKey) {
-        LOG.trace("Retrieving flow descriptor for flow hash : {}", flowRegistryKey.hashCode());
-        return flowRegistry.get(correctFlowRegistryKey(flowRegistry.keySet(), flowRegistryKey));
+    public FlowDescriptor retrieveDescriptor(@Nonnull final FlowRegistryKey flowRegistryKey) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Retrieving flow descriptor for flow hash : {}", flowRegistryKey.hashCode());
+        }
+
+        return flowRegistry.get(flowRegistryKey);
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized void storeDescriptor(final FlowRegistryKey flowRegistryKey, final FlowDescriptor flowDescriptor) {
-        final FlowRegistryKey correctFlowRegistryKey = correctFlowRegistryKey(flowRegistry.keySet(), flowRegistryKey);
-
+    public void storeDescriptor(@Nonnull final FlowRegistryKey flowRegistryKey,
+                                @Nonnull final FlowDescriptor flowDescriptor) {
         try {
-            if (hasMark(correctFlowRegistryKey)) {
-                // We are probably doing update of flow ID or table ID, so remove mark for removal of this flow
-                // and replace it with new value
-                marks.remove(correctFlowRegistryKey(marks, correctFlowRegistryKey));
-                flowRegistry.forcePut(correctFlowRegistryKey, flowDescriptor);
-                return;
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Storing flowDescriptor with table ID : {} and flow ID : {} for flow hash : {}",
+                        flowDescriptor.getTableKey().getId(), flowDescriptor.getFlowId().getValue(), flowRegistryKey.hashCode());
             }
 
-            LOG.trace("Storing flowDescriptor with table ID : {} and flow ID : {} for flow hash : {}",
-                flowDescriptor.getTableKey().getId(), flowDescriptor.getFlowId().getValue(), correctFlowRegistryKey.hashCode());
-
-            flowRegistry.put(correctFlowRegistryKey, flowDescriptor);
+            flowRegistry.put(flowRegistryKey, flowDescriptor);
         } catch (IllegalArgumentException ex) {
-            if (hasMark(flowRegistry.inverse().get(flowDescriptor))) {
-                // We are probably doing update of flow, but without changing flow ID or table ID, so we need to replace
-                // old value with new value, but keep the old value marked for removal
-                flowRegistry.forcePut(correctFlowRegistryKey, flowDescriptor);
-                return;
+            if (LOG.isWarnEnabled()) {
+                LOG.warn("Flow with flow ID {} already exists in table {}, generating alien flow ID", flowDescriptor.getFlowId().getValue(),
+                        flowDescriptor.getTableKey().getId());
             }
 
             // We are trying to store new flow to flow registry, but we already have different flow with same flow ID
             // stored in registry, so we need to create alien ID for this new flow here.
-            LOG.warn("Flow with flow ID {} already exists in table {}, generating alien flow ID", flowDescriptor.getFlowId().getValue(),
-                flowDescriptor.getTableKey().getId());
-
             flowRegistry.put(
-                correctFlowRegistryKey,
-                FlowDescriptorFactory.create(
-                    flowDescriptor.getTableKey().getId(),
-                    createAlienFlowId(flowDescriptor.getTableKey().getId())));
+                    flowRegistryKey,
+                    FlowDescriptorFactory.create(
+                            flowDescriptor.getTableKey().getId(),
+                            createAlienFlowId(flowDescriptor.getTableKey().getId())));
         }
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized void forEachEntry(final BiConsumer<FlowRegistryKey, FlowDescriptor> consumer) {
-        flowRegistry.forEach(consumer);
-    }
-
-    @Override
-    @GuardedBy("this")
-    public synchronized void store(final FlowRegistryKey flowRegistryKey) {
+    public void store(final FlowRegistryKey flowRegistryKey) {
         if (Objects.isNull(retrieveDescriptor(flowRegistryKey))) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Flow descriptor for flow hash : {} not found, generating alien flow ID", flowRegistryKey.hashCode());
+            }
+
             // We do not found flow in flow registry, that means it do not have any ID already assigned, so we need
             // to generate new alien flow ID here.
-            LOG.debug("Flow descriptor for flow hash : {} not found, generating alien flow ID", flowRegistryKey.hashCode());
-            final short tableId = flowRegistryKey.getTableId();
-            final FlowId alienFlowId = createAlienFlowId(tableId);
-            final FlowDescriptor flowDescriptor = FlowDescriptorFactory.create(tableId, alienFlowId);
-
-            // Finally we got flowDescriptor, so now we will store it to registry,
-            // so next time we won't need to generate it again
-            storeDescriptor(flowRegistryKey, flowDescriptor);
+            storeDescriptor(
+                    flowRegistryKey,
+                    FlowDescriptorFactory.create(
+                            flowRegistryKey.getTableId(),
+                            createAlienFlowId(flowRegistryKey.getTableId())));
         }
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized void addMark(final FlowRegistryKey flowRegistryKey) {
-        LOG.trace("Removing flow descriptor for flow hash : {}", flowRegistryKey.hashCode());
-        marks.add(flowRegistryKey);
-    }
-
-    @Override
-    @GuardedBy("this")
-    public synchronized boolean hasMark(final FlowRegistryKey flowRegistryKey) {
-        return Objects.nonNull(flowRegistryKey) && marks.contains(correctFlowRegistryKey(marks, flowRegistryKey));
+    public void addMark(final FlowRegistryKey flowRegistryKey) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Removing flow descriptor for flow hash : {}", flowRegistryKey.hashCode());
+        }
 
+        flowRegistry.remove(flowRegistryKey);
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized void processMarks() {
-        // Remove all flows that was marked for removal from flow registry and clear all marks.
-        marks.forEach(flowRegistry::remove);
-        marks.clear();
+    public void processMarks() {
+        // Do nothing
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized void forEach(final Consumer<FlowRegistryKey> consumer) {
-        flowRegistry.keySet().forEach(consumer);
+    public void forEach(final Consumer<FlowRegistryKey> consumer) {
+        synchronized (flowRegistry) {
+            flowRegistry.keySet().forEach(consumer);
+        }
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized int size() {
+    public int size() {
         return flowRegistry.size();
     }
 
     @Override
-    @GuardedBy("this")
-    public synchronized void close() {
+    public void close() {
         final Iterator<ListenableFuture<List<Optional<FlowCapableNode>>>> iterator = lastFillFutures.iterator();
 
-        // We need to force interrupt and clear all running futures that are trying to read flow IDs from datastore
+        // We need to force interrupt and clear all running futures that are trying to read flow IDs from data store
         while (iterator.hasNext()) {
             final ListenableFuture<List<Optional<FlowCapableNode>>> next = iterator.next();
             boolean success = next.cancel(true);
@@ -266,33 +235,6 @@ public class DeviceFlowRegistryImpl implements DeviceFlowRegistry {
         }
 
         flowRegistry.clear();
-        marks.clear();
-    }
-
-    @GuardedBy("this")
-    private FlowRegistryKey correctFlowRegistryKey(final Collection<FlowRegistryKey> flowRegistryKeys, final FlowRegistryKey key) {
-        if (Objects.isNull(key)) {
-            return null;
-        }
-
-        if (!flowRegistryKeys.contains(key)) {
-            // If we failed to compare FlowRegistryKey by hashCode, try to retrieve correct FlowRegistryKey
-            // from set of keys using custom comparator method for Match. This case can occur when we have different
-            // augmentations on extensions, or switch returned things like IP address or port in different format that
-            // we sent.
-            if (LOG.isTraceEnabled()) {
-                LOG.trace("Failed to retrieve flow descriptor for flow hash : {}, trying with custom equals method", key.hashCode());
-            }
-
-            for (final FlowRegistryKey flowRegistryKey : flowRegistryKeys) {
-                if (key.equals(flowRegistryKey)) {
-                    return flowRegistryKey;
-                }
-            }
-        }
-
-        // If we failed to find key at all or key is already present in set of keys, just return original key
-        return key;
     }
 
     @VisibleForTesting
index 68ad18ee5e6fe2fafba2cece66dbe0db8899bd4d..2638aaeee237c3479e2fa7ef64859fe8c2534fac 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.openflowplugin.impl.registry.flow;
 
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
@@ -19,13 +20,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 9.4.2015.
  */
 public class FlowDescriptorFactory {
+
     private FlowDescriptorFactory() {
         // Hide implicit constructor
     }
 
-    public static FlowDescriptor create(final short tableId, final FlowId fLowId) {
-        final TableKey tableKey = new TableKey(tableId);
-        return new FlowDescriptorDto(tableKey, fLowId);
+    @Nonnull
+    public static FlowDescriptor create(final short tableId, @Nonnull final FlowId flowId) {
+        return new FlowDescriptorDto(
+                new TableKey(tableId),
+                Preconditions.checkNotNull(flowId));
     }
 
     private static final class FlowDescriptorDto implements FlowDescriptor {
@@ -33,9 +37,7 @@ public class FlowDescriptorFactory {
         private final FlowId flowId;
         private final TableKey tableKey;
 
-        private FlowDescriptorDto(final TableKey tableKey, final FlowId flowId) {
-            Preconditions.checkNotNull(tableKey);
-            Preconditions.checkNotNull(flowId);
+        private FlowDescriptorDto(@Nonnull final TableKey tableKey, @Nonnull final FlowId flowId) {
             this.flowId = flowId;
             this.tableKey = tableKey;
         }
@@ -64,4 +66,5 @@ public class FlowDescriptorFactory {
             return tableKey;
         }
     }
+
 }
\ No newline at end of file
index a691b60ba2516d8e0e30129c00834f34b503cb22..8febbd1f9fa463be67e73568bbd29dd65ffc0dc1 100644 (file)
@@ -11,24 +11,27 @@ package org.opendaylight.openflowplugin.impl.registry.flow;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Preconditions;
 import java.math.BigInteger;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
-import org.opendaylight.openflowplugin.impl.util.MatchComparatorFactory;
+import org.opendaylight.openflowplugin.impl.util.MatchNormalizationUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 
-/**
- * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 8.4.2015.
- */
 public class FlowRegistryKeyFactory {
 
     private FlowRegistryKeyFactory() {
         // Hide implicit constructor
     }
 
-    public static FlowRegistryKey create(final short version, final Flow flow) {
-        return new FlowRegistryKeyDto(version, flow);
+    @Nonnull
+    public static FlowRegistryKey create(final short version, @Nonnull final Flow flow) {
+        //TODO: mandatory flow input values (or default values) should be specified via yang model
+        final short tableId = Preconditions.checkNotNull(flow.getTableId(), "flow tableId must not be null");
+        final int priority = MoreObjects.firstNonNull(flow.getPriority(), OFConstants.DEFAULT_FLOW_PRIORITY);
+        final BigInteger cookie = MoreObjects.firstNonNull(flow.getCookie(), OFConstants.DEFAULT_FLOW_COOKIE).getValue();
+        final Match match = MatchNormalizationUtil.normalizeMatch(MoreObjects.firstNonNull(flow.getMatch(), OFConstants.EMPTY_MATCH), version);
+        return new FlowRegistryKeyDto(tableId, priority, cookie, match);
     }
 
     private static final class FlowRegistryKeyDto implements FlowRegistryKey {
@@ -36,15 +39,15 @@ public class FlowRegistryKeyFactory {
         private final int priority;
         private final BigInteger cookie;
         private final Match match;
-        private final short version;
-
-        private FlowRegistryKeyDto(final short version, final Flow flow) {
-            //TODO: mandatory flow input values (or default values) should be specified via yang model
-            tableId = Preconditions.checkNotNull(flow.getTableId(), "flow tableId must not be null");
-            priority = MoreObjects.firstNonNull(flow.getPriority(), OFConstants.DEFAULT_FLOW_PRIORITY);
-            match = MoreObjects.firstNonNull(flow.getMatch(), OFConstants.EMPTY_MATCH);
-            cookie = MoreObjects.firstNonNull(flow.getCookie(), OFConstants.DEFAULT_FLOW_COOKIE).getValue();
-            this.version = version;
+
+        private FlowRegistryKeyDto(final short tableId,
+                                   final int priority,
+                                   @Nonnull final BigInteger cookie,
+                                   @Nonnull final Match match) {
+            this.tableId = tableId;
+            this.priority = priority;
+            this.cookie = cookie;
+            this.match = match;
         }
 
         @Override
@@ -62,7 +65,7 @@ public class FlowRegistryKeyFactory {
             return getPriority() == that.getPriority() &&
                     getTableId() == that.getTableId() &&
                     getCookie().equals(that.getCookie()) &&
-                    MatchComparatorFactory.createMatch().areObjectsEqual(version, getMatch(), that.getMatch());
+                    getMatch().equals(that.getMatch());
         }
 
         @Override
@@ -94,4 +97,5 @@ public class FlowRegistryKeyFactory {
             return match;
         }
     }
+
 }
index 6fb6d5c9ec6ed6f0897725a59b1857b6f9f90567..a3da37b9dfd5e131638cebfd668be06bfefd1c89 100644 (file)
@@ -13,9 +13,11 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
+import javax.annotation.concurrent.ThreadSafe;
 import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
 
+@ThreadSafe
 public class DeviceGroupRegistryImpl implements DeviceGroupRegistry {
 
     private final List<GroupId> groupIds = Collections.synchronizedList(new ArrayList<>());
@@ -31,11 +33,6 @@ public class DeviceGroupRegistryImpl implements DeviceGroupRegistry {
         marks.add(groupId);
     }
 
-    @Override
-    public boolean hasMark(final GroupId groupId) {
-        return marks.contains(groupId);
-    }
-
     @Override
     public void processMarks() {
         groupIds.removeAll(marks);
index a29dc3cb9d694ac895319625db6178e4017f3e23..c6623080aa7f5180595e119542eaa548b16d4db4 100644 (file)
@@ -13,9 +13,11 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
+import javax.annotation.concurrent.ThreadSafe;
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
 
+@ThreadSafe
 public class DeviceMeterRegistryImpl implements DeviceMeterRegistry {
 
     private final List<MeterId> meterIds = Collections.synchronizedList(new ArrayList<>());
@@ -31,11 +33,6 @@ public class DeviceMeterRegistryImpl implements DeviceMeterRegistry {
         marks.add(meterId);
     }
 
-    @Override
-    public boolean hasMark(final MeterId meterId) {
-        return marks.contains(meterId);
-    }
-
     @Override
     public void processMarks() {
         meterIds.removeAll(marks);
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/AddressNormalizationUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/AddressNormalizationUtil.java
new file mode 100644 (file)
index 0000000..b61e2b6
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.util;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.IpConversionUtil;
+import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility class used for converting OpenFlow port numbers, Ipv4 and Ipv6 addresses to normalized format.
+ */
+public class AddressNormalizationUtil {
+    private static final Logger LOG = LoggerFactory.getLogger(AddressNormalizationUtil.class);
+
+    private static final String NO_ETH_MASK = "ff:ff:ff:ff:ff:ff";
+    private static final String PREFIX_SEPARATOR = "/";
+
+    /**
+     * Extract port number from URI and convert it to OpenFlow specific textual representation.
+     *
+     * @param port            the OpenFlow port
+     * @param protocolVersion the OpenFLow protocol version
+     * @return normalized uri
+     */
+    @Nullable
+    public static Uri normalizeProtocolAgnosticPort(@Nullable final Uri port, final short protocolVersion) {
+        if (Objects.isNull(port)) {
+            return null;
+        }
+
+        return OpenflowPortsUtil.getProtocolAgnosticPortUri(protocolVersion, InventoryDataServiceUtil
+                .portNumberfromNodeConnectorId(OpenflowVersion.get(protocolVersion), port.getValue()));
+    }
+
+    /**
+     * Normalize Ipv6 address with prefix mask (ex. 1234:5678:9ABC::/76) and apply prefix mask to Ipv6 address.
+     *
+     * @param ipv6Prefix the Ipv6 prefix
+     * @return normalized Ipv6 prefix
+     */
+    @Nullable
+    public static Ipv6Prefix normalizeIpv6Prefix(@Nullable final Ipv6Prefix ipv6Prefix) {
+        if (Objects.isNull(ipv6Prefix)) {
+            return null;
+        }
+
+        final byte[] address = IetfInetUtil.INSTANCE.ipv6AddressBytes(IpConversionUtil.extractIpv6Address(ipv6Prefix));
+        final byte[] mask = IpConversionUtil.convertIpv6PrefixToByteArray(IpConversionUtil.extractIpv6Prefix(ipv6Prefix));
+        return normalizeIpv6Address(address, mask);
+    }
+
+    /**
+     * Normalize Ipv6 address and arbitrary mask and apply arbitrary mask to Ipv6 address.
+     *
+     * @param ipv6Address the Ipv4 address
+     * @param ipv4Mask    the Ipv4 mask
+     * @return normalized Ipv6 prefix
+     */
+    @Nullable
+    public static Ipv6Prefix normalizeIpv6Arbitrary(@Nullable final Ipv6Address ipv6Address, @Nullable final Ipv6ArbitraryMask ipv4Mask) {
+        if (Objects.isNull(ipv6Address)) {
+            return null;
+        }
+
+        final byte[] address = IetfInetUtil.INSTANCE.ipv6AddressBytes(ipv6Address);
+        final byte[] mask = IpConversionUtil.convertIpv6ArbitraryMaskToByteArray(ipv4Mask);
+        return normalizeIpv6Address(address, mask);
+    }
+
+    /**
+     * Normalize ipv 6 address without mask.
+     *
+     * @param ipv6Address the Ipv6 address
+     * @return normalized Ipv6 address
+     */
+    @Nullable
+    public static Ipv6Address normalizeIpv6AddressWithoutMask(@Nullable final Ipv6Address ipv6Address) {
+        final Ipv6Prefix ipv6Prefix = normalizeIpv6Arbitrary(ipv6Address, null);
+        return Objects.nonNull(ipv6Prefix)
+                ? new Ipv6Address(ipv6Prefix.getValue().split(PREFIX_SEPARATOR)[0])
+                : null;
+    }
+
+    /**
+     * Normalize Ipv4 address with prefix mask (ex. 192.168.0.1/24) and apply prefix mask to Ipv4 address.
+     *
+     * @param ipv4Prefix the Ipv4 prefix
+     * @return normalized Ipv4 prefix
+     */
+    @Nullable
+    public static Ipv4Prefix normalizeIpv4Prefix(@Nullable final Ipv4Prefix ipv4Prefix) {
+        if (Objects.isNull(ipv4Prefix)) {
+            return null;
+        }
+
+        final byte[] address = IetfInetUtil.INSTANCE.ipv4AddressBytes(IpConversionUtil.extractIpv4Address(ipv4Prefix));
+        final byte[] mask = IpConversionUtil.convertArbitraryMaskToByteArray(IpConversionUtil.extractIpv4AddressMask(ipv4Prefix));
+        return normalizeIpv4Address(address, mask);
+    }
+
+    /**
+     * Normalize Ipv4 address and arbitrary mask and apply arbitrary mask to Ipv4 address.
+     *
+     * @param ipv4Address the Ipv4 address
+     * @param ipv4Mask    the Ipv4 mask
+     * @return normalized Ipv4 prefix
+     */
+    @Nullable
+    public static Ipv4Prefix normalizeIpv4Arbitrary(@Nullable final Ipv4Address ipv4Address, @Nullable final DottedQuad ipv4Mask) {
+        if (Objects.isNull(ipv4Address)) {
+            return null;
+        }
+
+        final byte[] address = IetfInetUtil.INSTANCE.ipv4AddressBytes(ipv4Address);
+        final byte[] mask = IpConversionUtil.convertArbitraryMaskToByteArray(ipv4Mask);
+        return normalizeIpv4Address(address, mask);
+    }
+
+    /**
+     * Normalize Ipv4 address and arbitrary mask in byte array format and apply arbitrary mask to Ipv4 address.
+     *
+     * @param address Ipv4 address byte array
+     * @param mask    Ipv4 mask byte array
+     * @return normalized Ipv4 prefix
+     */
+    @Nullable
+    public static Ipv4Prefix normalizeIpv4Address(@Nullable final byte[] address, @Nullable final byte[] mask) {
+        final String addressPrefix = normalizeInetAddressWithMask(normalizeIpAddress(address, mask), mask);
+
+        if (Objects.isNull(addressPrefix)) {
+            return null;
+        }
+
+        return new Ipv4Prefix(addressPrefix);
+    }
+
+
+    /**
+     * Normalize Ipv6 address and arbitrary mask in byte array format and apply arbitrary mask to Ipv6 address.
+     *
+     * @param address Ipv6 address byte array
+     * @param mask    Ipv6 mask byte array
+     * @return normalized Ipv6 prefix
+     */
+    @Nullable
+    public static Ipv6Prefix normalizeIpv6Address(@Nullable final byte[] address, @Nullable final byte[] mask) {
+        final String addressPrefix = normalizeInetAddressWithMask(normalizeIpAddress(address, mask), mask);
+
+        if (Objects.isNull(addressPrefix)) {
+            return null;
+        }
+
+        return new Ipv6Prefix(addressPrefix);
+    }
+
+    /**
+     * Normalize generic IP address and arbitrary mask in byte array format and apply arbitrary mask to IP address.
+     *
+     * @param address address byte array
+     * @param mask    mask byte array
+     * @return normalized Inet address
+     */
+    @Nullable
+    public static InetAddress normalizeIpAddress(@Nullable final byte[] address, @Nullable final byte[] mask) {
+        if (Objects.isNull(address)) {
+            return null;
+        }
+
+        final byte[] result = new byte[address.length];
+
+        for (int i = 0; i < address.length; i++) {
+            result[i] = Objects.nonNull(mask) ?
+                    (byte) (address[i] & mask[i]) :
+                    address[i];
+        }
+
+        try {
+            return InetAddress.getByAddress(result);
+        } catch (UnknownHostException e) {
+            LOG.warn("Failed to recognize the host while normalizing IP address from bytes ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Convert arbitrary mask to prefix mask and append it to textual representation of Inet address
+     *
+     * @param address the address
+     * @param mask    the mask
+     * @return the string
+     */
+    @Nullable
+    public static String normalizeInetAddressWithMask(@Nullable final InetAddress address, @Nullable final byte[] mask) {
+        if (Objects.isNull(address)) {
+            return null;
+        }
+
+        return address.getHostAddress() +
+                (Objects.nonNull(mask)
+                        ? PREFIX_SEPARATOR + String.valueOf(IpConversionUtil.countBits(mask))
+                        : "");
+    }
+
+    /**
+     * Convert MAC address to it's lower case format
+     *
+     * @param macAddress the MAC address
+     * @return normalized MAC address
+     */
+    @Nullable
+    public static MacAddress normalizeMacAddress(@Nullable final MacAddress macAddress) {
+        if (Objects.isNull(macAddress)) {
+            return null;
+        }
+
+        return new MacAddress(macAddress.getValue().toLowerCase());
+    }
+
+    /**
+     * Convert MAC address mask to it's lower case format and if it is full F mask, return null
+     *
+     * @param macAddress the MAC address
+     * @return normalized MAC address
+     */
+    @Nullable
+    public static MacAddress normalizeMacAddressMask(@Nullable final MacAddress macAddress) {
+        final MacAddress normalizedMacAddress = normalizeMacAddress(macAddress);
+
+        if (Objects.isNull(normalizedMacAddress)) {
+            return null;
+        }
+
+        if (NO_ETH_MASK.equals(normalizedMacAddress.getValue())) {
+            return null;
+        }
+
+        return normalizedMacAddress;
+    }
+
+}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/IntegerIpAddress.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/IntegerIpAddress.java
deleted file mode 100644 (file)
index d4ae17c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.impl.util;
-
-/**
- * 4B base + 4B mask wrapper
- */
-public class IntegerIpAddress {
-
-    int ip;
-    int mask;
-
-    public IntegerIpAddress(final int ip, final int mask) {
-        this.ip = ip;
-        this.mask = mask;
-    }
-
-    public int getIp() {
-        return ip;
-    }
-
-    public int getMask() {
-        return mask;
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorFactory.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorFactory.java
deleted file mode 100644 (file)
index dc77ec6..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (c) 2013, 2015 IBM Corporation and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.util;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Optional;
-import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
-import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionResolvers;
-import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
-
-/**
- * Provides comparator for comparing according to various {@link Match} attributes
- *
- */
-public final class MatchComparatorFactory {
-
-    private MatchComparatorFactory() {
-        // NOOP
-    }
-
-    private static final Collection<SimpleComparator<Match>> MATCH_COMPARATORS = new ArrayList<>();
-    static {
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createEthernet());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createIcmpv4());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createInPhyPort());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createInPort());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createIp());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createL3());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createL4());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createProtocolMatchFields());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createMetadata());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createNull());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createTunnel());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createVlan());
-        MATCH_COMPARATORS.add(MatchComparatorFactory.createExtension());
-    }
-
-    private static SimpleComparator<Match> createExtension() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compare extension lists
-             */
-            @Override
-            public boolean areObjectsEqual(final short version, final Match statsMatch, final Match storedMatch) {
-                return ExtensionResolvers
-                    .getMatchExtensionResolver()
-                    .getExtension(statsMatch)
-                    .flatMap(statExt -> Optional.ofNullable(statExt.getExtensionList()))
-                    .map(statList -> ExtensionResolvers
-                        .getMatchExtensionResolver()
-                        .getExtension(storedMatch)
-                        .flatMap(storedExt -> Optional.ofNullable(storedExt.getExtensionList()))
-                        .filter(storedList -> statList.size() == storedList.size())
-                        .map(storedList -> {
-                            final Collection<ExtensionList> difference = new HashSet<>(statList);
-                            difference.removeAll(storedList);
-                            return difference.isEmpty();
-                        })
-                        .orElse(false))
-                    .orElse(!ExtensionResolvers
-                        .getMatchExtensionResolver()
-                        .getExtension(storedMatch)
-                        .flatMap(storedExt -> Optional.ofNullable(storedExt.getExtensionList()))
-                        .isPresent());
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createNull() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by whole object
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                return (statsMatch == null) == (storedMatch == null);
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createVlan() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by VLAN
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getVlanMatch() == null) {
-                    if (statsMatch.getVlanMatch() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getVlanMatch().equals(statsMatch.getVlanMatch())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createTunnel() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by tunnel
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getTunnel() == null) {
-                    if (statsMatch.getTunnel() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getTunnel().equals(statsMatch.getTunnel())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createProtocolMatchFields() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by protocol fields
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getProtocolMatchFields() == null) {
-                    if (statsMatch.getProtocolMatchFields() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getProtocolMatchFields().equals(statsMatch.getProtocolMatchFields())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createMetadata() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by metadata
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getMetadata() == null) {
-                    if (statsMatch.getMetadata() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getMetadata().equals(statsMatch.getMetadata())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createL4() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by layer4
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getLayer4Match() == null) {
-                    if (statsMatch.getLayer4Match() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getLayer4Match().equals(statsMatch.getLayer4Match())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createL3() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by layer3
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getLayer3Match() == null) {
-                    if (statsMatch.getLayer3Match() != null) {
-                        return false;
-                    }
-                } else if (!MatchComparatorHelper.layer3MatchEquals(statsMatch.getLayer3Match(), storedMatch.getLayer3Match())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createIp() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by Ip
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getIpMatch() == null) {
-                    if (statsMatch.getIpMatch() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getIpMatch().equals(statsMatch.getIpMatch())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-
-    /**
-     * Converts both ports in node connector id format to number format and compare them
-     *
-     * @param version openflow version
-     * @param left first object to compare
-     * @param right second object to compare
-     * @return true if equal
-     */
-    private static boolean arePortNumbersEqual(short version, NodeConnectorId left, NodeConnectorId right) {
-        final OpenflowVersion ofVersion = OpenflowVersion.get(version);
-
-        final Long leftPort = InventoryDataServiceUtil.portNumberfromNodeConnectorId(ofVersion, left);
-        final Long rightPort = InventoryDataServiceUtil.portNumberfromNodeConnectorId(ofVersion, right);
-
-        if (leftPort == null) {
-            if (rightPort != null) {
-                return false;
-            }
-        } else if (!leftPort.equals(rightPort)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private static SimpleComparator<Match> createInPort() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by InPort
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getInPort() == null) {
-                    if (statsMatch.getInPort() != null) {
-                        return false;
-                    }
-                } else if (!arePortNumbersEqual(version, storedMatch.getInPort(), statsMatch.getInPort())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createInPhyPort() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by InPhyPort
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getInPhyPort() == null) {
-                    if (statsMatch.getInPhyPort() != null) {
-                        return false;
-                    }
-                } else if (!arePortNumbersEqual(version, storedMatch.getInPhyPort(), statsMatch.getInPhyPort())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createEthernet() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by Ethernet
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getEthernetMatch() == null) {
-                    if (statsMatch.getEthernetMatch() != null) {
-                        return false;
-                    }
-                } else if (!MatchComparatorHelper.ethernetMatchEquals(statsMatch.getEthernetMatch(), storedMatch.getEthernetMatch())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    private static SimpleComparator<Match> createIcmpv4() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares by Icmpv4
-             */
-            @Override
-            public boolean areObjectsEqual(short version, Match statsMatch, Match storedMatch) {
-                if (storedMatch == null) {
-                    return false;
-                }
-                if (storedMatch.getIcmpv4Match() == null) {
-                    if (statsMatch.getIcmpv4Match() != null) {
-                        return false;
-                    }
-                } else if (!storedMatch.getIcmpv4Match().equals(statsMatch.getIcmpv4Match())) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-    public static SimpleComparator<Match> createMatch() {
-        return new SimpleComparator<Match>() {
-            /**
-             * Compares flows by whole match
-             */
-            @Override
-            public boolean areObjectsEqual(short version, final Match statsFlow, final Match storedFlow) {
-                if (statsFlow == null) {
-                    if (storedFlow != null) {
-                        return false;
-                    }
-                } else if (!compareMatches(version, statsFlow, storedFlow)) {
-                    return false;
-                }
-                return true;
-            }
-        };
-    }
-
-
-    /**
-     * Explicit equals method to compare the 'match' for flows stored in the data-stores and flow fetched from the switch.
-     * Flow installation process has three steps
-     * 1) Store flow in config data store
-     * 2) and send it to plugin for installation
-     * 3) Flow gets installed in switch
-     *
-     * The flow user wants to install and what finally gets installed in switch can be slightly different.
-     * E.g, If user installs flow with src/dst ip=10.0.0.1/24, when it get installed in the switch
-     * src/dst ip will be changes to 10.0.0.0/24 because of netmask of 24. When statistics manager fetch
-     * stats it gets 10.0.0.0/24 rather then 10.0.0.1/24. Custom match takes care of by using masked ip
-     * while comparing two ip addresses.
-     *
-     * Sometimes when user don't provide few values that is required by flow installation request, like
-     * priority,hard timeout, idle timeout, cookies etc, plugin usages default values before sending
-     * request to the switch. So when statistics manager gets flow statistics, it gets the default value.
-     * But the flow stored in config data store don't have those defaults value. I included those checks
-     * in the customer flow/match equal function.
-     */
-    private static boolean compareMatches(final short version, final Match statsMatch, final Match storedMatch) {
-        if (statsMatch == storedMatch) {
-            return true;
-        }
-
-        for (SimpleComparator<Match> matchComp : MATCH_COMPARATORS) {
-            if (!matchComp.areObjectsEqual(version, statsMatch, storedMatch)) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorHelper.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorHelper.java
deleted file mode 100644 (file)
index c6b3174..0000000
+++ /dev/null
@@ -1,722 +0,0 @@
-/**
- * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.impl.util;
-
-import com.google.common.annotations.VisibleForTesting;
-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.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-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.ArpMatch;
-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.Ipv4MatchArbitraryBitMask;
-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.Ipv6MatchArbitraryBitMask;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * @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;
-    private static final int SHIFT_OCTET_2 = 16;
-    private static final int SHIFT_OCTET_3 = 8;
-    private static final int SHIFT_OCTET_4 = 0;
-    private static final int POSITION_OCTET_1 = 0;
-    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 DEFAULT_IPV6_ARBITRARY_BIT_MASK = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
-    private static final String PREFIX_SEPARATOR = "/";
-    private static final int IPV4_ADDRESS_LENGTH = 32;
-    private static final int IPV6_ADDRESS_LENGTH = 128;
-    private static final int BYTE_SIZE = 8;
-    private static final String NO_ETH_MASK = "ff:ff:ff:ff:ff:ff";
-
-    /*
-     * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case
-     * (upper or lower or mix). Ethernet Match which controller receives from switch is always an upper case string.
-     * Default EthernetMatch equals doesn't use equalsIgnoreCase() and hence it fails. E.g User provided mac address
-     * string in flow match is aa:bb:cc:dd:ee:ff and when controller fetch statistic data, openflow driver library
-     * returns AA:BB:CC:DD:EE:FF and default eqauls fails here.
-     */
-    @VisibleForTesting
-    static boolean ethernetMatchEquals(final EthernetMatch statsEthernetMatch, final EthernetMatch storedEthernetMatch) {
-        boolean verdict = true;
-        final Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch);
-        if (checkNullValues != null) {
-            verdict = checkNullValues;
-        } else {
-            verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetSource(),
-                    storedEthernetMatch.getEthernetSource());
-            if (verdict) {
-                verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetDestination(),
-                        storedEthernetMatch.getEthernetDestination());
-            }
-            if (verdict) {
-                if (statsEthernetMatch.getEthernetType() == null) {
-                    if (storedEthernetMatch.getEthernetType() != null) {
-                        verdict = false;
-                    }
-                } else {
-                    verdict = statsEthernetMatch.getEthernetType().equals(storedEthernetMatch.getEthernetType());
-                }
-            }
-        }
-        return verdict;
-    }
-
-    static boolean ethernetMatchFieldsEquals(final MacAddressFilter statsEthernetMatchFields,
-                                             final MacAddressFilter storedEthernetMatchFields) {
-        boolean verdict = true;
-        final Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields);
-        if (checkNullValues != null) {
-            verdict = checkNullValues;
-        } else {
-            verdict = macAddressEquals(statsEthernetMatchFields.getAddress(), storedEthernetMatchFields.getAddress());
-            if (verdict) {
-                verdict = macAddressMaskEquals(statsEthernetMatchFields.getMask(), storedEthernetMatchFields.getMask());
-            }
-        }
-        return verdict;
-    }
-
-    static boolean macAddressEquals(final MacAddress statsMacAddress, final MacAddress storedMacAddress) {
-        boolean verdict = true;
-        final Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress);
-        if (checkNullValues != null) {
-            verdict = checkNullValues;
-        } else {
-            verdict = statsMacAddress.getValue().equalsIgnoreCase(storedMacAddress.getValue());
-        }
-        return verdict;
-    }
-
-    static boolean macAddressMaskEquals(final MacAddress statsMacAddressMask, final MacAddress storedMacAddressMask) {
-        boolean verdict = true;
-        //User sent the mask with all bit set, which actually means no mask. Switch might just ignore it.
-        if(statsMacAddressMask == null && storedMacAddressMask != null &&
-                storedMacAddressMask.getValue().equalsIgnoreCase(NO_ETH_MASK)) {
-            return verdict;
-        }
-        final Boolean checkNullValues = checkNullValues(statsMacAddressMask, storedMacAddressMask);
-        if (checkNullValues != null) {
-            verdict = checkNullValues;
-        } else {
-            verdict = statsMacAddressMask.getValue().equalsIgnoreCase(storedMacAddressMask.getValue());
-        }
-        return verdict;
-    }
-
-    @VisibleForTesting
-    static boolean layer3MatchEquals(final Layer3Match statsLayer3Match, final Layer3Match storedLayer3Match) {
-        boolean verdict = true;
-        if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match) {
-            final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match;
-            final Ipv4Match storedIpv4Match = (Ipv4Match) storedLayer3Match;
-            verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(storedIpv4Match.getIpv4Destination(),
-                    statsIpv4Match.getIpv4Destination());
-            if (verdict) {
-                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(statsIpv4Match.getIpv4Source(),
-                        storedIpv4Match.getIpv4Source());
-            }
-        } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6Match) {
-            final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match;
-            final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match;
-            verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(storedIpv6Match.getIpv6Destination(),
-                    statsIpv6Match.getIpv6Destination());
-            if (verdict) {
-                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(statsIpv6Match.getIpv6Source(),
-                        storedIpv6Match.getIpv6Source());
-            }
-        } 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 storedDstIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
-                            storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
-                    String statsDstIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
-                            statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
-                    if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue(),
-                            statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue())) {
-                        verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress,
-                                statsDstIpAddress);
-                    } else {
-                        verdict = false;
-                        return verdict;
-                    }
-                }
-                if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
-                    String storedSrcIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
-                            ,storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
-                    String statsSrcIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
-                            ,statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
-                    if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue(),
-                            statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue())) {
-                        verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress,
-                                statsSrcIpAddress);
-                    } 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 if (statsLayer3Match instanceof Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4Match) {
-            // 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 storedIpv4Match = (Ipv4Match) storedLayer3Match;
-            final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) statsLayer3Match;
-            if (statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
-                Ipv4Prefix ipv4PrefixDestination;
-                if (statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) {
-                    byte[] destByteMask = convertArbitraryMaskToByteArray(statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
-                    ipv4PrefixDestination = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask);
-                } else {
-                    ipv4PrefixDestination = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask());
-                }
-                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, storedIpv4Match.getIpv4Destination());
-                if (verdict == false) {
-                    return verdict;
-                }
-            }
-            if (statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
-                Ipv4Prefix ipv4PrefixSource;
-                if (statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) {
-                    byte[] srcByteMask = convertArbitraryMaskToByteArray(statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
-                    ipv4PrefixSource = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask);
-                } else {
-                    ipv4PrefixSource = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask());
-                }
-                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, storedIpv4Match.getIpv4Source());
-            }
-        } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) {
-            // At this moment storedIpv6MatchArbitraryBitMask & statsIpv6MatchArbitraryBitMask will always have non null arbitrary masks.
-            // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv6Match.
-            // Eg:- stats src/dest  -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:0000:FFFF:FFFF:FFF0
-            //     stored src/dest  -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:0000:FFFF:FFFF:FFF0
-            final Ipv6MatchArbitraryBitMask statsIpv6MatchArbitraryBitMask= (Ipv6MatchArbitraryBitMask) statsLayer3Match;
-            final Ipv6MatchArbitraryBitMask storedIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) storedLayer3Match;
-            if ((storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null |
-                    storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null)) {
-                if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
-                    String storedDstIpAddress = normalizeIpv6Address(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(),
-                            storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
-                    String statsDstIpAddress = normalizeIpv6Address(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(),
-                            statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
-                    String storedDstMask = extractIpv6CanonicalForm(storedIpv6MatchArbitraryBitMask.
-                            getIpv6DestinationArbitraryBitmask().getValue()).getHostAddress();
-                    String statsDstMask = extractIpv6CanonicalForm(statsIpv6MatchArbitraryBitMask.
-                            getIpv6DestinationArbitraryBitmask().getValue()).getHostAddress();
-                    if (MatchComparatorHelper.compareStringNullSafe(storedDstMask,statsDstMask)) {
-                        verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress,
-                                statsDstIpAddress);
-                    } else {
-                        verdict = false;
-                        return verdict;
-                    }
-                }
-                if (storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
-                    String storedSrcIpAddress = normalizeIpv6Address(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask()
-                            ,storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
-                    String statsSrcIpAddress = normalizeIpv6Address(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask()
-                            ,statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
-                    String storedSrcMask = extractIpv6CanonicalForm(storedIpv6MatchArbitraryBitMask.
-                            getIpv6SourceArbitraryBitmask().getValue()).getHostAddress();
-                    String statsSrcMask = extractIpv6CanonicalForm(statsIpv6MatchArbitraryBitMask.
-                            getIpv6SourceArbitraryBitmask().getValue()).getHostAddress();
-                    if (MatchComparatorHelper.compareStringNullSafe(storedSrcMask, statsSrcMask)) {
-                        verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress,
-                                statsSrcIpAddress);
-                    } else {
-                        verdict = false;
-                    }
-                }
-            } else {
-                final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
-                if (nullCheckOut != null) {
-                    verdict = nullCheckOut;
-                } else {
-                    verdict = storedLayer3Match.equals(statsLayer3Match);
-                }
-            }
-        } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) {
-            // Here stored netmask is an instance of Ipv6MatchArbitraryBitMask, 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 -> 2001:2001:2001:2001:2001:2001:2001:2001/124
-            // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0
-            final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match;
-            final Ipv6MatchArbitraryBitMask storedIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) storedLayer3Match;
-            if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
-                Ipv6Prefix ipv6PrefixDestination;
-                if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask() != null) {
-                    byte[] destByteMask = convertIpv6ArbitraryMaskToByteArray(storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
-                    ipv6PrefixDestination = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), destByteMask);
-                } else {
-                    ipv6PrefixDestination = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask());
-                }
-                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixDestination, statsIpv6Match.getIpv6Destination());
-                if (verdict == false) {
-                    return verdict;
-                }
-            }
-            if (storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
-                Ipv6Prefix ipv6PrefixSource;
-                if (storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask() != null) {
-                    byte[] srcByteMask = convertIpv6ArbitraryMaskToByteArray(storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
-                    ipv6PrefixSource = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask(), srcByteMask);
-                } else {
-                    ipv6PrefixSource = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask());
-                }
-                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, statsIpv6Match.getIpv6Source());
-            }
-        } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6Match) {
-            // Here stored netmask is an instance of Ipv6MatchArbitraryBitMask, 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 -> 2001:2001:2001:2001:2001:2001:2001:2001/124
-            // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0
-            final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match;
-            final Ipv6MatchArbitraryBitMask statsIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) statsLayer3Match;
-            if (statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
-                Ipv6Prefix ipv6PrefixDestination;
-                if (statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask() != null) {
-                    byte[] destByteMask = convertIpv6ArbitraryMaskToByteArray(statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
-                    ipv6PrefixDestination = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), destByteMask);
-                } else {
-                    ipv6PrefixDestination = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask());
-                }
-                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixDestination, storedIpv6Match.getIpv6Destination());
-                if (verdict == false) {
-                    return verdict;
-                }
-            }
-            if (statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
-                Ipv6Prefix ipv6PrefixSource;
-                if (statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask() != null) {
-                    byte[] srcByteMask = convertIpv6ArbitraryMaskToByteArray(statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
-                    ipv6PrefixSource = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask(), srcByteMask);
-                } else {
-                    ipv6PrefixSource = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask());
-                }
-                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, storedIpv6Match.getIpv6Source());
-            }
-        } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) {
-            verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match);
-        } else {
-            final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
-            if (nullCheckOut != null) {
-                verdict = nullCheckOut;
-            } else {
-                verdict = storedLayer3Match.equals(statsLayer3Match);
-            }
-        }
-        return verdict;
-    }
-
-    static boolean arpMatchEquals(final ArpMatch statsArpMatch, final ArpMatch storedArpMatch) {
-
-        Integer statsOp = statsArpMatch.getArpOp();
-        Integer storedOp = storedArpMatch.getArpOp();
-
-        Boolean nullCheck = checkNullValues(statsOp, storedOp);
-        if (nullCheck != null) {
-            if (nullCheck == false) {
-                return false;
-            }
-        } else if (!statsOp.equals(storedOp)) {
-            return false;
-        }
-
-        Ipv4Prefix statsIp = statsArpMatch.getArpSourceTransportAddress();
-        Ipv4Prefix storedIp = storedArpMatch.getArpSourceTransportAddress();
-        if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
-            return false;
-        }
-
-        statsIp = statsArpMatch.getArpTargetTransportAddress();
-        storedIp = storedArpMatch.getArpTargetTransportAddress();
-        if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
-            return false;
-        }
-
-        MacAddressFilter statsMac = statsArpMatch.getArpSourceHardwareAddress();
-        MacAddressFilter storedMac = storedArpMatch.getArpSourceHardwareAddress();
-        if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
-            return false;
-        }
-
-        statsMac = statsArpMatch.getArpTargetHardwareAddress();
-        storedMac = storedArpMatch.getArpTargetHardwareAddress();
-        if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
-            return false;
-        }
-
-        return true;
-    }
-
-
-    /**
-     * TODO: why don't we use the default Ipv4Prefix.equals()?
-     *
-     * @param statsIpAddress
-     * @param storedIpAddress
-     * @return true if IPv4prefixes equals
-     */
-    static boolean IpAddressEquals(final Ipv4Prefix statsIpAddress, final Ipv4Prefix storedIpAddress) {
-        final IntegerIpAddress statsIpAddressInt = MatchComparatorHelper.strIpToIntIp(statsIpAddress.getValue());
-        final IntegerIpAddress storedIpAddressInt = MatchComparatorHelper.strIpToIntIp(storedIpAddress.getValue());
-
-        if (ipAndMaskBasedMatch(statsIpAddressInt, storedIpAddressInt)) {
-            return true;
-        }
-        if (ipBasedMatch(statsIpAddressInt, storedIpAddressInt)) {
-            return true;
-        }
-        return false;
-    }
-
-    static boolean ipAndMaskBasedMatch(final IntegerIpAddress statsIpAddressInt,
-                                       final IntegerIpAddress storedIpAddressInt) {
-        return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) == (storedIpAddressInt.getIp() & storedIpAddressInt
-                .getMask()));
-    }
-
-    static boolean ipBasedMatch(final IntegerIpAddress statsIpAddressInt, final IntegerIpAddress storedIpAddressInt) {
-        return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp());
-    }
-
-
-    private static boolean IpAddressEquals(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) {
-        final String[] statsIpMask = statsIpv6.getValue().split("/");
-        final String[] storedIpMask = storedIpv6.getValue().split("/");
-        if (! (statsIpMask.length > 1 && storedIpMask.length > 1 &&  statsIpMask[1].equals(storedIpMask[1]))){
-            return false;
-        }
-
-        final int prefix = Integer.parseInt(statsIpMask[1]);
-        final int byteIndex = prefix/BYTE_SIZE;
-        final int lastByteBits = BYTE_SIZE - (prefix % BYTE_SIZE);
-        final InetAddress statsIp = InetAddresses.forString(statsIpMask[0]);
-        final InetAddress storedIp = InetAddresses.forString(storedIpMask[0]);
-        byte[] statsIpArr = Arrays.copyOfRange(statsIp.getAddress(),0,byteIndex+1);
-        byte[] storedIpArr = Arrays.copyOfRange(storedIp.getAddress(),0,byteIndex+1);
-        statsIpArr[byteIndex] = (byte) (statsIpArr[byteIndex] & (0XFF << lastByteBits));
-        storedIpArr[byteIndex] = (byte) (storedIpArr[byteIndex] & (0XFF << lastByteBits));
-        if(Arrays.equals(statsIpArr,storedIpArr)) {
-            return true;
-        }
-        return false;
-    }
-
-    static Boolean checkNullValues(final Object v1, final Object v2) {
-        Boolean verdict = null;
-        if (v1 == null && v2 != null) {
-            verdict = Boolean.FALSE;
-        } else if (v1 != null && v2 == null) {
-            verdict = Boolean.FALSE;
-        } else if (v1 == null && v2 == null) {
-            verdict = Boolean.TRUE;
-        }
-        return verdict;
-    }
-
-    static boolean compareIpv4PrefixNullSafe(final Ipv4Prefix statsIpv4, final Ipv4Prefix storedIpv4) {
-        boolean verdict = true;
-        final Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4);
-        if (checkDestNullValuesOut != null) {
-            verdict = checkDestNullValuesOut;
-        } 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;
-    }
-
-    private static boolean compareIpv6PrefixNullSafe(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) {
-        boolean verdict = true;
-        final Boolean checkDestNullValuesOut = checkNullValues(statsIpv6, storedIpv6);
-        if (checkDestNullValuesOut != null) {
-            verdict = checkDestNullValuesOut;
-        } else if (!IpAddressEquals(statsIpv6, storedIpv6)) {
-            verdict = false;
-        }
-        return verdict;
-    }
-
-    /**
-     * Method return integer version of ip address. Converted int will be mask if mask specified
-     */
-    static IntegerIpAddress strIpToIntIp(final String ipAddresss) {
-
-        final String[] parts = ipAddresss.split("/");
-        final String ip = parts[0];
-        int prefix;
-
-        if (parts.length < 2) {
-            prefix = DEFAULT_SUBNET;
-        } else {
-            prefix = Integer.parseInt(parts[1]);
-            if (prefix < 0 || prefix > IPV4_MASK_LENGTH) {
-                final StringBuilder stringBuilder = new StringBuilder(
-                        "Valid values for mask are from range 0 - 32. Value ");
-                stringBuilder.append(prefix);
-                stringBuilder.append(" is invalid.");
-                throw new IllegalStateException(stringBuilder.toString());
-            }
-        }
-
-        IntegerIpAddress integerIpAddress = null;
-
-        final Inet4Address addr = ((Inet4Address) InetAddresses.forString(ip));
-        final byte[] addrBytes = addr.getAddress();
-        // FIXME: what is meaning of anding with 0xFF? Probably could be removed.
-        final int ipInt = ((addrBytes[POSITION_OCTET_1] & 0xFF) << SHIFT_OCTET_1)
-                | ((addrBytes[POSITION_OCTET_2] & 0xFF) << SHIFT_OCTET_2)
-                | ((addrBytes[POSITION_OCTET_3] & 0xFF) << SHIFT_OCTET_3)
-                | ((addrBytes[POSITION_OCTET_4] & 0xFF) << SHIFT_OCTET_4);
-
-        // FIXME: Is this valid?
-        final int mask = 0xffffffff << DEFAULT_SUBNET - prefix;
-
-        integerIpAddress = new IntegerIpAddress(ipInt, mask);
-
-        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) {
-        if (arrayList.size()>0 && arrayList.size()< IPV4_MASK_LENGTH ) {
-            // checks 0*1* case - Leading zeros in arrayList are truncated
-            return true;
-        } else {
-            //checks 1*0*1 case
-            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) {
-            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;
-    }
-
-    private static final byte[] convertIpv6ArbitraryMaskToByteArray ( final Ipv6ArbitraryMask mask) {
-        String maskValue;
-        if (mask.getValue() != null) {
-            maskValue = mask.getValue();
-        } else {
-            maskValue = DEFAULT_IPV6_ARBITRARY_BIT_MASK;
-        }
-        InetAddress maskInIpv6Format = null;
-        try {
-            maskInIpv6Format = InetAddress.getByName(maskValue);
-        } catch (UnknownHostException e) {
-            LOG.error("Failed to convert string mask value to ipv6 format ", e);
-        }
-        return maskInIpv6Format.getAddress();
-    }
-
-    static String normalizeIpv4Address(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;
-    }
-
-    private static String normalizeIpv6Address(final Ipv6Address ipAddress, final Ipv6ArbitraryMask netMask) {
-        byte[] ipAddressParts = convertIpv6ToBytes(ipAddress.getValue());
-        byte[] netMaskParts  = convertIpv6ToBytes(netMask.getValue());
-        byte[] actualIpv6Bytes = new byte[16];
-
-        for (int i=0; i<ipAddressParts.length;i++) {
-            byte ipAddressPart= (byte) (ipAddressParts[i] & netMaskParts[i]);
-            actualIpv6Bytes[i] = ipAddressPart;
-        }
-        InetAddress ipv6Address = null;
-        try {
-            ipv6Address = InetAddress.getByAddress(actualIpv6Bytes);
-        } catch (UnknownHostException e) {
-            LOG.error("Failed to recognize the host while normalizing IPv6 address from bytes ", e);
-        }
-        return ipv6Address.getHostAddress();
-    }
-
-    private static byte[] convertIpv6ToBytes(final String ipv6Address) {
-        return extractIpv6CanonicalForm(ipv6Address).getAddress();
-    }
-
-    private static InetAddress extractIpv6CanonicalForm(final String ipv6Address) {
-        InetAddress address = null;
-        try {
-            address = InetAddress.getByName(ipv6Address);
-        } catch (UnknownHostException e) {
-            LOG.error("Failed to recognize the host while converting IPv6 to bytes ", e);
-        }
-        return address;
-    }
-
-    static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final byte [] bytemask){
-        return createPrefix(ipv4Address, String.valueOf(countBits(bytemask)));
-    }
-
-    private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final byte [] bytemask) {
-        return createPrefix(ipv6Address, String.valueOf(countBits(bytemask)));
-    }
-
-    private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final String mask) {
-        if (mask != null && !mask.isEmpty()) {
-            return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + mask);
-        } else {
-            return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + IPV6_ADDRESS_LENGTH);
-        }
-    }
-
-    private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address) {
-        return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + IPV6_ADDRESS_LENGTH);
-    }
-
-    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);
-        }
-    }
-}
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchNormalizationUtil.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/MatchNormalizationUtil.java
new file mode 100644 (file)
index 0000000..64be028
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.util;
+
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Arbitrary;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv4Prefix;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6AddressWithoutMask;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Arbitrary;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Prefix;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddress;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddressMask;
+import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeProtocolAgnosticPort;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.annotation.Nonnull;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.extension.api.GroupingLooseResolver;
+import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionResolvers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+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.Ipv4MatchArbitraryBitMask;
+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.Ipv6MatchArbitraryBitMask;
+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.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionListGrouping;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ * Utility class for match normalization
+ */
+public final class MatchNormalizationUtil {
+    // Cache normalizers for common OpenFlow versions
+    private static final Map<Short, Set<Function<MatchBuilder, MatchBuilder>>> NORMALIZERS = ImmutableMap
+            .<Short, Set<Function<MatchBuilder, MatchBuilder>>>builder()
+            .put(OFConstants.OFP_VERSION_1_0, createNormalizers(OFConstants.OFP_VERSION_1_0).collect(Collectors.toSet()))
+            .put(OFConstants.OFP_VERSION_1_3, createNormalizers(OFConstants.OFP_VERSION_1_3).collect(Collectors.toSet()))
+            .build();
+
+    private MatchNormalizationUtil() {
+        throw new RuntimeException("Creating instance of util classes is prohibited");
+    }
+
+    /**
+     * Normalize match.
+     *
+     * @param match   the OpenFlow match
+     * @param version the OpenFlow version
+     * @return normalized OpenFlow match
+     */
+    @Nonnull
+    public static Match normalizeMatch(@Nonnull final Match match, final short version) {
+        final MatchBuilder matchBuilder = new MatchBuilder(match);
+
+        Optional.ofNullable(NORMALIZERS.get(version))
+                .orElseGet(() -> createNormalizers(version).collect(Collectors.toSet()))
+                .forEach(normalizer -> normalizer.apply(matchBuilder));
+
+        return matchBuilder.build();
+    }
+
+    @Nonnull
+    private static Stream<Function<MatchBuilder, MatchBuilder>> createNormalizers(final short version) {
+        return Stream.of(
+                MatchNormalizationUtil::normalizeExtensionMatch,
+                MatchNormalizationUtil::normalizeEthernetMatch,
+                MatchNormalizationUtil::normalizeArpMatch,
+                MatchNormalizationUtil::normalizeTunnelIpv4Match,
+                MatchNormalizationUtil::normalizeIpv4Match,
+                MatchNormalizationUtil::normalizeIpv4MatchArbitraryBitMask,
+                MatchNormalizationUtil::normalizeIpv6Match,
+                MatchNormalizationUtil::normalizeIpv6MatchArbitraryBitMask,
+                (match) -> normalizeInPortMatch(match, version),
+                (match) -> normalizeInPhyPortMatch(match, version));
+    }
+
+    @Nonnull
+    @SuppressWarnings("unchecked")
+    private static MatchBuilder normalizeExtensionMatch(@Nonnull final MatchBuilder match) {
+        final GroupingLooseResolver<GeneralExtensionListGrouping> matchExtensionResolver =
+                ExtensionResolvers.getMatchExtensionResolver();
+
+        return matchExtensionResolver
+                .getExtension(match.build())
+                .flatMap(statExt -> Optional.ofNullable(statExt.getExtensionList()))
+                .map(extensionLists -> {
+                    matchExtensionResolver.getClasses().forEach(aClass -> match
+                            .removeAugmentation((Class<? extends Augmentation<Match>>) aClass));
+
+                    return match.addAugmentation(
+                            GeneralAugMatchNotifUpdateFlowStats.class,
+                            new GeneralAugMatchNotifUpdateFlowStatsBuilder()
+                                    .setExtensionList(extensionLists)
+                                    .build());
+                })
+                .orElse(match);
+    }
+
+    @Nonnull
+    private static MatchBuilder normalizeInPortMatch(@Nonnull final MatchBuilder match, final short version) {
+        return Optional
+                .ofNullable(match.getInPort())
+                .flatMap(inPort -> Optional.ofNullable(normalizeProtocolAgnosticPort(inPort, version)))
+                .map(inPortUri -> match.setInPort(new NodeConnectorId(inPortUri)))
+                .orElse(match);
+    }
+
+    @Nonnull
+    private static MatchBuilder normalizeInPhyPortMatch(@Nonnull final MatchBuilder match, final short version) {
+        return Optional
+                .ofNullable(match.getInPhyPort())
+                .flatMap(inPhyPort -> Optional.ofNullable(normalizeProtocolAgnosticPort(inPhyPort, version)))
+                .map(inPhyPortUri -> match.setInPhyPort(new NodeConnectorId(inPhyPortUri)))
+                .orElse(match);
+    }
+
+    @Nonnull
+    private static MatchBuilder normalizeArpMatch(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getLayer3Match())
+                .filter(ArpMatch.class::isInstance)
+                .map(ArpMatch.class::cast)
+                .map(arp -> match.setLayer3Match(new ArpMatchBuilder(arp)
+                        .setArpSourceHardwareAddress(Optional
+                                .ofNullable(arp.getArpSourceHardwareAddress())
+                                .map(arpSource -> new ArpSourceHardwareAddressBuilder(arpSource)
+                                        .setAddress(normalizeMacAddress(arpSource.getAddress()))
+                                        .setMask(normalizeMacAddress(arpSource.getMask()))
+                                        .build())
+                                .orElse(arp.getArpSourceHardwareAddress()))
+                        .setArpTargetHardwareAddress(Optional
+                                .ofNullable(arp.getArpTargetHardwareAddress())
+                                .map(arpTarget -> new ArpTargetHardwareAddressBuilder(arpTarget)
+                                        .setAddress(normalizeMacAddress(arpTarget.getAddress()))
+                                        .setMask(normalizeMacAddress(arpTarget.getMask()))
+                                        .build())
+                                .orElse(arp.getArpTargetHardwareAddress()))
+                        .setArpSourceTransportAddress(normalizeIpv4Prefix(arp.getArpSourceTransportAddress()))
+                        .setArpTargetTransportAddress(normalizeIpv4Prefix(arp.getArpTargetTransportAddress()))
+                        .build())
+                )
+                .orElse(match);
+    }
+
+
+    @Nonnull
+    private static MatchBuilder normalizeTunnelIpv4Match(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getLayer3Match())
+                .filter(TunnelIpv4Match.class::isInstance)
+                .map(TunnelIpv4Match.class::cast)
+                .map(tunnelIpv4 -> match.setLayer3Match(new TunnelIpv4MatchBuilder(tunnelIpv4)
+                        .setTunnelIpv4Source(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Source()))
+                        .setTunnelIpv4Destination(normalizeIpv4Prefix(tunnelIpv4.getTunnelIpv4Destination()))
+                        .build()))
+                .orElse(match);
+    }
+
+    @Nonnull
+    private static MatchBuilder normalizeIpv4Match(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getLayer3Match())
+                .filter(Ipv4Match.class::isInstance)
+                .map(Ipv4Match.class::cast)
+                .map(ipv4 -> match.setLayer3Match(new Ipv4MatchBuilder(ipv4)
+                        .setIpv4Source(normalizeIpv4Prefix(ipv4.getIpv4Source()))
+                        .setIpv4Destination(normalizeIpv4Prefix(ipv4.getIpv4Destination()))
+                        .build()))
+                .orElse(match);
+    }
+
+    @Nonnull
+    private static MatchBuilder normalizeIpv4MatchArbitraryBitMask(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getLayer3Match())
+                .filter(Ipv4MatchArbitraryBitMask.class::isInstance)
+                .map(Ipv4MatchArbitraryBitMask.class::cast)
+                .map(ipv4arbitrary -> match.setLayer3Match(new Ipv4MatchBuilder()
+                        .setIpv4Source(normalizeIpv4Arbitrary(
+                                ipv4arbitrary.getIpv4SourceAddressNoMask(),
+                                ipv4arbitrary.getIpv4SourceArbitraryBitmask()))
+                        .setIpv4Destination(normalizeIpv4Arbitrary(
+                                ipv4arbitrary.getIpv4DestinationAddressNoMask(),
+                                ipv4arbitrary.getIpv4DestinationArbitraryBitmask()))
+                        .build()))
+                .orElse(match);
+    }
+
+
+    @Nonnull
+    private static MatchBuilder normalizeIpv6Match(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getLayer3Match())
+                .filter(Ipv6Match.class::isInstance)
+                .map(Ipv6Match.class::cast)
+                .map(ipv6 -> match.setLayer3Match(new Ipv6MatchBuilder(ipv6)
+                        .setIpv6NdSll(normalizeMacAddress(ipv6.getIpv6NdSll()))
+                        .setIpv6NdTll(normalizeMacAddress(ipv6.getIpv6NdTll()))
+                        .setIpv6NdTarget(normalizeIpv6AddressWithoutMask(ipv6.getIpv6NdTarget()))
+                        .setIpv6Source(normalizeIpv6Prefix(ipv6.getIpv6Source()))
+                        .setIpv6Destination(normalizeIpv6Prefix(ipv6.getIpv6Destination()))
+                        .build()))
+                .orElse(match);
+    }
+
+
+    @Nonnull
+    private static MatchBuilder normalizeIpv6MatchArbitraryBitMask(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getLayer3Match())
+                .filter(Ipv6MatchArbitraryBitMask.class::isInstance)
+                .map(Ipv6MatchArbitraryBitMask.class::cast)
+                .map(ipv6Arbitrary -> match.setLayer3Match(new Ipv6MatchBuilder()
+                        .setIpv6Source(normalizeIpv6Arbitrary(
+                                ipv6Arbitrary.getIpv6SourceAddressNoMask(),
+                                ipv6Arbitrary.getIpv6SourceArbitraryBitmask()))
+                        .setIpv6Destination(normalizeIpv6Arbitrary(
+                                ipv6Arbitrary.getIpv6DestinationAddressNoMask(),
+                                ipv6Arbitrary.getIpv6DestinationArbitraryBitmask()))
+                        .build()))
+                .orElse(match);
+    }
+
+    @Nonnull
+    private static MatchBuilder normalizeEthernetMatch(@Nonnull final MatchBuilder match) {
+        return Optional
+                .ofNullable(match.getEthernetMatch())
+                .map(eth -> match.setEthernetMatch(new EthernetMatchBuilder(eth)
+                        .setEthernetSource(Optional
+                                .ofNullable(eth.getEthernetSource())
+                                .map(filter -> new EthernetSourceBuilder(filter)
+                                        .setAddress(normalizeMacAddress(filter.getAddress()))
+                                        .setMask(normalizeMacAddressMask(filter.getMask()))
+                                        .build())
+                                .orElse(eth.getEthernetSource()))
+                        .setEthernetDestination(Optional
+                                .ofNullable(eth.getEthernetDestination())
+                                .map(filter -> new EthernetDestinationBuilder(filter)
+                                        .setAddress(normalizeMacAddress(filter.getAddress()))
+                                        .setMask(normalizeMacAddressMask(filter.getMask()))
+                                        .build())
+                                .orElse(eth.getEthernetDestination()))
+                        .build()))
+                .orElse(match);
+    }
+
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/SimpleComparator.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/SimpleComparator.java
deleted file mode 100644 (file)
index dfcea9b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (c) 2013, 2015 IBM Corporation and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.util;
-
-public interface SimpleComparator<T> {
-
-    boolean areObjectsEqual(short version, T obj1, T obj2);
-
-}
index d4f5906426ca986ed02b9246a3a46e1e26d2395d..df6b4863b591f68585b0242d5ce62acee98cc6c1 100644 (file)
@@ -211,7 +211,7 @@ public class DeviceFlowRegistryImplTest {
     @Test
     public void testRemoveDescriptor() throws Exception {
         deviceFlowRegistry.addMark(key);
-        Assert.assertEquals(1, deviceFlowRegistry.getAllFlowDescriptors().size());
+        Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
     }
 
     @Test
index 859542376e2e2aed892df0070b868e9ac7071857..67b5a5887d1315914e27f51cdf2c4c0a02d6e904 100644 (file)
@@ -26,7 +26,7 @@ public class FlowDescriptorDtoTest {
         Assert.assertNotNull(flowDescriptor.getTableKey());
     }
 
-    @Test(expected = NullPointerException.class)
+    @Test(expected = Exception.class)
     public void testCreateNegative1() throws Exception {
         FlowDescriptorFactory.create((short) 1, null);
     }
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/AddressNormalizationUtilTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/AddressNormalizationUtilTest.java
new file mode 100644 (file)
index 0000000..0c19036
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
+
+public class AddressNormalizationUtilTest {
+
+    @Test
+    public void normalizeProtocolAgnosticPortOF10() throws Exception {
+        final Uri left = new Uri("openflow:1:INPORT");
+        final Uri right = new Uri("INPORT");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeProtocolAgnosticPort(left, OFConstants.OFP_VERSION_1_0)
+        );
+    }
+
+    @Test
+    public void normalizeProtocolAgnosticPortOF13() throws Exception {
+        final Uri left = new Uri("openflow:1:ANY");
+        final Uri right = new Uri("ANY");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeProtocolAgnosticPort(left, OFConstants.OFP_VERSION_1_3)
+        );
+    }
+
+    @Test
+    public void normalizeIpv6Prefix() throws Exception {
+        final Ipv6Prefix left = new Ipv6Prefix("1E3D:5678:9ABC::/24");
+        final Ipv6Prefix right = new Ipv6Prefix("1e3d:5600:0:0:0:0:0:0/24");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeIpv6Prefix(left)
+        );
+    }
+
+    @Test
+    public void normalizeIpv6Arbitrary() throws Exception {
+        final Ipv6Address leftAddress = new Ipv6Address("1E3D:5678:9ABC::");
+        final Ipv6ArbitraryMask leftMask = new Ipv6ArbitraryMask("FFFF:FF00::");
+        final Ipv6Prefix right = new Ipv6Prefix("1e3d:5600:0:0:0:0:0:0/24");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeIpv6Arbitrary(leftAddress, leftMask)
+        );
+    }
+
+    @Test
+    public void normalizeIpv6AddressWithoutMask() throws Exception {
+        final Ipv6Address left = new Ipv6Address("1E3D:5678:9ABC::");
+        final Ipv6Address right = new Ipv6Address("1e3d:5678:9abc:0:0:0:0:0");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeIpv6AddressWithoutMask(left)
+        );
+    }
+
+    @Test
+    public void normalizeIpv4Prefix() throws Exception {
+        final Ipv4Prefix left = new Ipv4Prefix("192.168.72.1/16");
+        final Ipv4Prefix right = new Ipv4Prefix("192.168.0.0/16");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeIpv4Prefix(left)
+        );
+    }
+
+    @Test
+    public void normalizeIpv4Arbitrary() throws Exception {
+        final Ipv4Address leftAddress = new Ipv4Address("192.168.72.1");
+        final DottedQuad leftMask = new DottedQuad("255.255.0.0");
+        final Ipv4Prefix right = new Ipv4Prefix("192.168.0.0/16");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeIpv4Arbitrary(leftAddress, leftMask)
+        );
+    }
+
+    @Test
+    public void normalizeMacAddress() throws Exception {
+        final MacAddress left = new MacAddress("01:23:45:AB:CD:EF");
+        final MacAddress right = new MacAddress("01:23:45:ab:cd:ef");
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeMacAddress(left)
+        );
+    }
+
+    @Test
+    public void normalizeMacAddressMask() throws Exception {
+        final MacAddress left = new MacAddress("FF:FF:FF:FF:FF:FF");
+        final MacAddress right = null;
+
+        assertEquals(
+                right,
+                AddressNormalizationUtil.normalizeMacAddressMask(left)
+        );
+    }
+
+}
\ No newline at end of file
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorHelperTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/MatchComparatorHelperTest.java
deleted file mode 100644 (file)
index 5c29fc8..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (c) 2014, 2017 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.impl.util;
-
-import org.junit.Test;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
-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.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMaskBuilder;
-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.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-/**
- * @author sai.marapareddy@gmail.com (arbitrary masks)
- */
-
-/**
- * test of {@link MatchComparatorHelper}
- */
-public class MatchComparatorHelperTest {
-
-    /**
-     * mask for /32
-     */
-    private static final int DEFAULT_IPV4_MASK = 0xffffffff;
-
-    /**
-     * mask for /30
-     */
-    private static final int IPV4_30_MASK = 0xfffffffc;
-    private static final int IP_ADDRESS = 0xC0A80101;
-
-    /**
-     * The test of conversion valid IP addres without mask to binary form.
-     */
-    @Test
-    public void validIpWithoutMaskTest() {
-        IntegerIpAddress intIp = MatchComparatorHelper.strIpToIntIp("192.168.1.1");
-        assertEquals(IP_ADDRESS, intIp.getIp());
-        assertEquals(DEFAULT_IPV4_MASK, intIp.getMask());
-    }
-
-    /**
-     * The test of conversion of valid IP address with valid mask to binary form.
-     */
-    @Test
-    public void validIpWithValidMaskTest() {
-        IntegerIpAddress intIp = MatchComparatorHelper.strIpToIntIp("192.168.1.1/30");
-        assertEquals(IP_ADDRESS, intIp.getIp());
-        assertEquals(IPV4_30_MASK, intIp.getMask());
-    }
-
-    /**
-     * The test of conversion of valid IP address invalid mask to binary form.
-     */
-    @Test
-    public void validIpWithInvalidMaskTest() {
-        try {
-            MatchComparatorHelper.strIpToIntIp("192.168.1.1/40");
-        } catch (IllegalStateException e) {
-            assertEquals("Valid values for mask are from range 0 - 32. Value 40 is invalid.", e.getMessage());
-            return;
-        }
-        fail("IllegalStateException was awaited (40 subnet is invalid)");
-    }
-
-    /**
-     * The test of conversion invalid IP address with valid mask to binary form.
-     */
-    @Test
-    public void invalidIpWithValidMaskTest() {
-        try {
-            MatchComparatorHelper.strIpToIntIp("257.168.1.1/25");
-        } catch (IllegalArgumentException e) {
-            assertEquals("'257.168.1.1' is not an IP string literal.", e.getMessage());
-        }
-    }
-
-    @Test
-    public void ethernetMatchEqualsTest() {
-        final EthernetMatchBuilder statsEthernetBuilder = new EthernetMatchBuilder();
-        final EthernetMatchBuilder storedEthernetBuilder = new EthernetMatchBuilder();
-
-        assertEquals(true, MatchComparatorHelper.ethernetMatchEquals(null, null));
-
-        statsEthernetBuilder.setEthernetSource(new EthernetSourceBuilder().setAddress(
-                new MacAddress("11:22:33:44:55:66")).build());
-        storedEthernetBuilder.setEthernetSource(new EthernetSourceBuilder().setAddress(
-                new MacAddress("11:22:33:44:55:77")).build());
-        assertEquals(false,
-                MatchComparatorHelper.ethernetMatchEquals(statsEthernetBuilder.build(), storedEthernetBuilder.build()));
-
-        storedEthernetBuilder.setEthernetSource(new EthernetSourceBuilder().setAddress(
-                new MacAddress("11:22:33:44:55:66")).build());
-        statsEthernetBuilder.setEthernetDestination(new EthernetDestinationBuilder().setAddress(
-                new MacAddress("66:55:44:33:22:11")).build());
-        storedEthernetBuilder.setEthernetDestination(new EthernetDestinationBuilder().setAddress(
-                new MacAddress("77:55:44:33:22:11")).build());
-        assertEquals(false,
-                MatchComparatorHelper.ethernetMatchEquals(statsEthernetBuilder.build(), storedEthernetBuilder.build()));
-
-        storedEthernetBuilder.setEthernetDestination(new EthernetDestinationBuilder().setAddress(
-                new MacAddress("66:55:44:33:22:11")).build());
-        statsEthernetBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long) 1)).build());
-        storedEthernetBuilder.setEthernetType(new EthernetTypeBuilder().setType(new EtherType((long) 1)).build());
-        assertEquals(true,
-                MatchComparatorHelper.ethernetMatchEquals(statsEthernetBuilder.build(), storedEthernetBuilder.build()));
-
-        statsEthernetBuilder.setEthernetType(null).build();
-        assertEquals(false,
-                MatchComparatorHelper.ethernetMatchEquals(statsEthernetBuilder.build(), storedEthernetBuilder.build()));
-
-        storedEthernetBuilder.setEthernetType(null).build();
-        assertEquals(true,
-                MatchComparatorHelper.ethernetMatchEquals(statsEthernetBuilder.build(), storedEthernetBuilder.build()));
-
-    }
-
-    // Please see following bug for more details https://bugs.opendaylight.org/show_bug.cgi?id=7910
-    @Test
-    public void ethernetMatchWithFullMaskTest() {
-        final EthernetSourceBuilder statsBuilder = new EthernetSourceBuilder();
-        final EthernetSourceBuilder storedBuilder = new EthernetSourceBuilder();
-
-        assertEquals(true, MatchComparatorHelper.ethernetMatchFieldsEquals(null, null));
-
-        statsBuilder.setAddress(new MacAddress("11:22:33:44:55:66"));
-
-        storedBuilder.setAddress(new MacAddress("11:22:33:44:55:66"));
-        storedBuilder.setMask(new MacAddress("FF:FF:FF:FF:FF:FF"));
-
-        assertEquals(true,
-                MatchComparatorHelper.ethernetMatchFieldsEquals(statsBuilder.build(), storedBuilder.build()));
-    }
-
-    @Test
-    public void ethernetMatchFieldsEqualsTest() {
-        final EthernetSourceBuilder statsBuilder = new EthernetSourceBuilder();
-        final EthernetSourceBuilder storedBuilder = new EthernetSourceBuilder();
-
-        assertEquals(true, MatchComparatorHelper.ethernetMatchFieldsEquals(null, null));
-
-        statsBuilder.setAddress(new MacAddress("11:22:33:44:55:66"));
-        storedBuilder.setAddress(new MacAddress("11:22:33:44:55:77"));
-        assertEquals(false,
-                MatchComparatorHelper.ethernetMatchFieldsEquals(statsBuilder.build(), storedBuilder.build()));
-
-        storedBuilder.setAddress(new MacAddress("11:22:33:44:55:66"));
-        assertEquals(true, MatchComparatorHelper.ethernetMatchFieldsEquals(statsBuilder.build(), storedBuilder.build()));
-    }
-
-    @Test
-    public void macAddressEqualsTest() {
-        assertEquals(true, MatchComparatorHelper.macAddressEquals(null, null));
-        assertEquals(true, MatchComparatorHelper.macAddressEquals(new MacAddress("11:22:33:44:55:66"), new MacAddress(
-                "11:22:33:44:55:66")));
-        assertEquals(false, MatchComparatorHelper.macAddressEquals(new MacAddress("11:22:33:44:55:66"), new MacAddress(
-                "11:22:33:44:55:77")));
-    }
-
-    @Test
-    public void checkNullValuesTest() {
-        assertEquals(false, MatchComparatorHelper.checkNullValues(null, ""));
-        assertEquals(false, MatchComparatorHelper.checkNullValues("", null));
-        assertEquals(true, MatchComparatorHelper.checkNullValues(null, null));
-        assertTrue(MatchComparatorHelper.checkNullValues("", "") == null);
-    }
-
-    @Test
-    public void compareIpv4PrefixNullSafeTest() {
-        assertEquals(true, MatchComparatorHelper.compareIpv4PrefixNullSafe(null, null));
-        assertEquals(true, MatchComparatorHelper.compareIpv4PrefixNullSafe(new Ipv4Prefix("192.168.1.1/31"),
-                new Ipv4Prefix("192.168.1.1/31")));
-
-        assertEquals(false, MatchComparatorHelper.compareIpv4PrefixNullSafe(new Ipv4Prefix("192.168.1.1/31"),
-                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;
-
-    @Test
-    public void ipBasedMatchTest() {
-        // are equals because only IP address is compared
-        assertEquals(true, MatchComparatorHelper.ipBasedMatch(new IntegerIpAddress(ip_192_168_1_1, 32),
-                new IntegerIpAddress(ip_192_168_1_1, 16)));
-    }
-
-    @Test
-    public void ipAndMaskBasedMatchTest() {
-        // true because both cases are network 192.168.1.0
-        assertEquals(true, MatchComparatorHelper.ipBasedMatch(new IntegerIpAddress(ip_192_168_1_1, 31),
-                new IntegerIpAddress(ip_192_168_1_1, 30)));
-
-        // false because first is network 192.168.1.0 and second is 192.168.1.4
-        assertEquals(false, MatchComparatorHelper.ipBasedMatch(new IntegerIpAddress(ip_192_168_1_1, 31),
-                new IntegerIpAddress(ip_192_168_1_4, 30)));
-    }
-
-    @Test
-    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 layer3MatchEqualsIpv6Test() {
-        final Ipv6MatchBuilder statsBuilder = new Ipv6MatchBuilder();
-        final Ipv6MatchBuilder storedBuilder = new Ipv6MatchBuilder();
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:5D99/64"));
-        storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/64"));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("aabb:1234:2acf:000d:0000:0000:0000:5d99/64"));
-        storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/64"));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000C:0000:0000:0000:5D99/64"));
-        storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/64"));
-        assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000C:0000:0000:0000:5D99/63"));
-        storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:4D99/63"));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000D:0000:0000:0000:5D99/63"));
-        storedBuilder.setIpv6Destination(new Ipv6Prefix("AABB:1234:2ACF:000E:0000:0000:0000:4D99/63"));
-        assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.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.normalizeIpv4Address(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"));
-    }
-
-    @Test
-    public void layer3MatchEqualsIpv6ArbitraryMaskTest(){
-        final Ipv6MatchBuilder statsBuilder = new Ipv6MatchBuilder();
-        final Ipv6MatchArbitraryBitMaskBuilder storedBuilder = new Ipv6MatchArbitraryBitMaskBuilder();
-        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("1:2:3:4:5:6:7:8/16"));
-        storedBuilder.setIpv6DestinationAddressNoMask(new Ipv6Address("1:2:3:4:5:6:7:8"));
-        storedBuilder.setIpv6DestinationArbitraryBitmask(new Ipv6ArbitraryMask("FFFF:0000:0000:0000:0000:0000:0000:0000"));
-        statsBuilder.setIpv6Source(new Ipv6Prefix("1:2:3:4:5:6:7:8/32"));
-        storedBuilder.setIpv6SourceAddressNoMask(new Ipv6Address("1:2:3:4:5:6:7:8"));
-        storedBuilder.setIpv6SourceArbitraryBitmask(new Ipv6ArbitraryMask("FFFF:FFFF::"));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
-    }
-
-
-    @Test
-    public void layer3MatchEqualsIpv6ArbitraryMaskRandomTest() {
-        final Ipv6MatchArbitraryBitMaskBuilder statsBuilder = new Ipv6MatchArbitraryBitMaskBuilder();
-        final Ipv6MatchArbitraryBitMaskBuilder storedBuilder = new Ipv6MatchArbitraryBitMaskBuilder();
-        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
-        statsBuilder.setIpv6DestinationAddressNoMask(new Ipv6Address("1::8"));
-        statsBuilder.setIpv6DestinationArbitraryBitmask(new Ipv6ArbitraryMask("FFFF::FFFF"));
-        storedBuilder.setIpv6DestinationAddressNoMask(new Ipv6Address("1:92:93:94:95:96:97:8"));
-        storedBuilder.setIpv6DestinationArbitraryBitmask(new Ipv6ArbitraryMask("FFFF::FFFF"));
-        statsBuilder.setIpv6SourceAddressNoMask(new Ipv6Address("1::8"));
-        statsBuilder.setIpv6SourceArbitraryBitmask(new Ipv6ArbitraryMask("FFFF::FFFF"));
-        storedBuilder.setIpv6SourceAddressNoMask(new Ipv6Address("1:92:93:94:95:96:97:8"));
-        storedBuilder.setIpv6SourceArbitraryBitmask(new Ipv6ArbitraryMask("FFFF::FFFF"));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
-    }
-
-    @Test
-    public void layer3MatchEqualsIpv6ArbitraryMaskEqualsNullTest() {
-        final Ipv6MatchBuilder statsBuilder = new Ipv6MatchBuilder();
-        final Ipv6MatchArbitraryBitMaskBuilder storedBuilder = new Ipv6MatchArbitraryBitMaskBuilder();
-        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
-        statsBuilder.setIpv6Source(new Ipv6Prefix("1:2:3:4:5:6:7:8/128"));
-        storedBuilder.setIpv6DestinationAddressNoMask(new Ipv6Address("1:2:3:4:5:6:7:8"));
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("1:2:3:4:5:6::/128"));
-        storedBuilder.setIpv6SourceAddressNoMask(new Ipv6Address("1:2:3:4:5:6::"));
-        assertEquals(false, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
-    }
-
-    @Test
-    public void layer3MatchEqualsIpv6ArbitraryEmptyBitMaskTest(){
-        final Ipv6MatchBuilder statsBuilder = new Ipv6MatchBuilder();
-        final Ipv6MatchArbitraryBitMaskBuilder storedBuilder = new Ipv6MatchArbitraryBitMaskBuilder();
-        assertEquals(true,MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(),storedBuilder.build()));
-        statsBuilder.setIpv6Destination(new Ipv6Prefix("1:2:3:4:5:6:7:8/128"));
-        storedBuilder.setIpv6DestinationAddressNoMask(new Ipv6Address("1:2:3:4:5:6:7:8"));
-        statsBuilder.setIpv6Source(new Ipv6Prefix("1:2:3:4:5:6::/128"));
-        storedBuilder.setIpv6SourceAddressNoMask(new Ipv6Address("1:2:3:4:5:6::"));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(statsBuilder.build(), storedBuilder.build()));
-        assertEquals(true, MatchComparatorHelper.layer3MatchEquals(null, null));
-    }
-}
index 1180766924e02bd72251d09983b7efb99ca99ddd..a14eb4335314e54539754d829386fd9610f5d394 100644 (file)
@@ -721,7 +721,7 @@ public final class IpConversionUtil {
 
     public static final byte[] convertIpv6ArbitraryMaskToByteArray(final Ipv6ArbitraryMask mask) {
         String maskValue;
-        if (mask.getValue() != null) {
+        if (mask != null && mask.getValue() != null) {
             maskValue  = mask.getValue();
         } else {
             maskValue = DEFAULT_IPV6_ARBITRARY_BITMASK;