[ONOS-4612]Update SFC flows inline with the Official OVS NSH patch

Change-Id: If58517841096a939860d88aa78eca7cae46b9935
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
index 4f3a5a0..27b3a22 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
@@ -48,7 +48,7 @@
     private static final String TENANT_ID_NOT_NULL = "Tenant id can not be null.";
     private static final String NAME_NOT_NULL = "Name can not be null.";
     private static final String ETHER_TYPE_NOT_NULL = "Ether Type can not be null.";
-    private static final int DEFAULT_CLASSIFIER_PRIORITY = 0xFFFF;
+    private static final int DEFAULT_CLASSIFIER_PRIORITY = 0xCB20;
 
     /**
      * Constructor to create default flow classifier.
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
index 879c7ea..9d66de3 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
@@ -22,7 +22,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -42,11 +41,13 @@
     private final String description;
     private final List<PortPairGroupId> portPairGroupList;
     private final List<FlowClassifierId> flowClassifierList;
+    private final PortChain oldPortChain;
 
     private final Map<FiveTuple, LoadBalanceId> sfcLoadBalanceIdMap = new ConcurrentHashMap<>();
     private final Map<LoadBalanceId, List<PortPairId>> sfcLoadBalancePathMap = new ConcurrentHashMap<>();
     private final Map<LoadBalanceId, List<DeviceId>> sfcClassifiersMap = new ConcurrentHashMap<>();
     private final Map<LoadBalanceId, List<DeviceId>> sfcForwardersMap = new ConcurrentHashMap<>();
+
     /**
      * Default constructor to create port chain.
      *
@@ -58,9 +59,10 @@
      * @param flowClassifierList flow classifier list
      */
     private DefaultPortChain(PortChainId portChainId, TenantId tenantId,
-                             String name, String description,
-                             List<PortPairGroupId> portPairGroupList,
-                             List<FlowClassifierId> flowClassifierList) {
+            String name, String description,
+            List<PortPairGroupId> portPairGroupList,
+            List<FlowClassifierId> flowClassifierList,
+            PortChain portChain) {
 
         this.portChainId = portChainId;
         this.tenantId = tenantId;
@@ -68,6 +70,20 @@
         this.description = description;
         this.portPairGroupList = portPairGroupList;
         this.flowClassifierList = flowClassifierList;
+        this.oldPortChain = portChain;
+    }
+
+    /**
+     * To create port chain for update with old port chain.
+     *
+     * @param newPortChain updated port chain
+     * @param oldPortChain old port chain
+     * @return port chain
+     */
+    public static PortChain create(PortChain newPortChain, PortChain oldPortChain) {
+        return new DefaultPortChain(newPortChain.portChainId(), newPortChain.tenantId(),
+                                    newPortChain.name(), newPortChain.description(),
+                                    newPortChain.portPairGroups(), newPortChain.flowClassifiers(), oldPortChain);
     }
 
     /**
@@ -109,7 +125,7 @@
 
     @Override
     public List<PortPairGroupId> portPairGroups() {
-        return  ImmutableList.copyOf(portPairGroupList);
+        return ImmutableList.copyOf(portPairGroupList);
     }
 
     @Override
@@ -118,6 +134,11 @@
     }
 
     @Override
+    public PortChain oldPortChain() {
+        return oldPortChain;
+    }
+
+    @Override
     public void addLoadBalancePath(FiveTuple fiveTuple, LoadBalanceId id,
                                    List<PortPairId> path) {
         this.sfcLoadBalanceIdMap.put(fiveTuple, id);
@@ -136,14 +157,14 @@
 
     @Override
     public void removeSfcClassifiers(LoadBalanceId id, List<DeviceId> classifierList) {
-        List<DeviceId> list = getSfcClassifiers(id);
+        List<DeviceId> list = sfcClassifiersMap.get(id);
         list.removeAll(classifierList);
         this.sfcForwardersMap.put(id, list);
     }
 
     @Override
     public void removeSfcForwarders(LoadBalanceId id, List<DeviceId> forwarderList) {
-        List<DeviceId> list = getSfcForwarders(id);
+        List<DeviceId> list = sfcForwardersMap.get(id);
         list.removeAll(forwarderList);
         this.sfcForwardersMap.put(id, list);
     }
@@ -192,7 +213,7 @@
     }
 
     @Override
-    public Optional<LoadBalanceId> matchPath(List<PortPairId> path) {
+    public LoadBalanceId matchPath(List<PortPairId> path) {
 
         LoadBalanceId id = null;
         for (Map.Entry<LoadBalanceId, List<PortPairId>> entry : sfcLoadBalancePathMap.entrySet()) {
@@ -202,7 +223,7 @@
                 break;
             }
         }
-        return Optional.of(id);
+        return id;
     }
 
     @Override
@@ -267,6 +288,7 @@
         private String description;
         private List<PortPairGroupId> portPairGroupList;
         private List<FlowClassifierId> flowClassifierList;
+        private PortChain portChain;
 
         @Override
         public Builder setId(PortChainId portChainId) {
@@ -312,7 +334,7 @@
             checkNotNull(portPairGroupList, "Port pair groups cannot be null");
 
             return new DefaultPortChain(portChainId, tenantId, name, description,
-                                        portPairGroupList, flowClassifierList);
+                                        portPairGroupList, flowClassifierList, portChain);
         }
     }
 }
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
index 9817b0a..af929dd 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
@@ -95,6 +95,13 @@
     }
 
     @Override
+    public void resetLoad() {
+        for (PortPairId portPairId : portPairList) {
+            portPairLoadMap.put(portPairId, new Integer(0));
+        }
+    }
+
+    @Override
     public int getLoad(PortPairId portPairId) {
         return portPairLoadMap.get(portPairId);
     }
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
index 2906411..c431c7a 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
@@ -16,7 +16,6 @@
 package org.onosproject.vtnrsc;
 
 import java.util.List;
-import java.util.Optional;
 import java.util.Set;
 
 import org.onosproject.net.DeviceId;
@@ -74,6 +73,13 @@
     List<FlowClassifierId> flowClassifiers();
 
     /**
+     * Returns the old port chain.
+     *
+     * @return old port chain
+     */
+    PortChain oldPortChain();
+
+    /**
      * Adds a new load balanced path.
      *
      * @param fiveTuple five tuple from the packet
@@ -182,7 +188,7 @@
      * @param path load balanced path
      * @return load balance id if the path matches, null otherwise.
      */
-    Optional<LoadBalanceId> matchPath(List<PortPairId> path);
+    LoadBalanceId matchPath(List<PortPairId> path);
 
     /**
      * Returns whether this port chain is an exact match to the port chain given
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
index bdcfd1d..0114470 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
@@ -67,6 +67,11 @@
     void addLoad(PortPairId portPairId);
 
     /**
+     * Reset the load for all the port pairs in the group.
+     */
+    void resetLoad();
+
+    /**
      * Get the load on the given port pair id.
      *
      * @param portPairId port pair id
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
index 25fca33..5521d2e 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
@@ -15,8 +15,10 @@
  */
 package org.onosproject.vtnrsc.flowclassifier.impl;
 
-import static org.slf4j.LoggerFactory.getLogger;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.UUID;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -24,6 +26,7 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpPrefix;
 import org.onlab.util.KryoNamespace;
 import org.onosproject.event.AbstractListenerManager;
 import org.onosproject.store.serializers.KryoNamespaces;
@@ -33,8 +36,11 @@
 import org.onosproject.store.service.MultiValuedTimestamp;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.WallClockTimestamp;
-import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.DefaultFlowClassifier;
 import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
 import org.onosproject.vtnrsc.flowclassifier.FlowClassifierEvent;
 import org.onosproject.vtnrsc.flowclassifier.FlowClassifierListener;
 import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
@@ -71,7 +77,8 @@
         KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
                 .register(KryoNamespaces.API)
                 .register(MultiValuedTimestamp.class)
-                .register(FlowClassifier.class);
+                .register(FlowClassifier.class, FlowClassifierId.class, UUID.class, IpPrefix.class,
+                          VirtualPortId.class, DefaultFlowClassifier.class, TenantId.class);
         flowClassifierStore = storageService
                 .<FlowClassifierId, FlowClassifier>eventuallyConsistentMapBuilder()
                 .withName("flowclassifierstore").withSerializer(serializer)
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
index 21c848b..21a3d2d 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
@@ -19,6 +19,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.Collections;
+import java.util.UUID;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -28,6 +29,7 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.util.KryoNamespace;
 import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.net.DeviceId;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.EventuallyConsistentMap;
 import org.onosproject.store.service.EventuallyConsistentMapEvent;
@@ -35,8 +37,15 @@
 import org.onosproject.store.service.MultiValuedTimestamp;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultPortChain;
+import org.onosproject.vtnrsc.FiveTuple;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.LoadBalanceId;
 import org.onosproject.vtnrsc.PortChain;
 import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
 import org.onosproject.vtnrsc.portchain.PortChainEvent;
 import org.onosproject.vtnrsc.portchain.PortChainListener;
 import org.onosproject.vtnrsc.portchain.PortChainService;
@@ -71,7 +80,9 @@
         KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
                 .register(KryoNamespaces.API)
                 .register(MultiValuedTimestamp.class)
-                .register(PortChain.class);
+                .register(PortChain.class, PortChainId.class, UUID.class, PortPairGroupId.class,
+                          FlowClassifierId.class, FiveTuple.class, LoadBalanceId.class, DeviceId.class,
+                          DefaultPortChain.class, PortPairId.class, TenantId.class);
 
         portChainStore = storageService
                 .<PortChainId, PortChain>eventuallyConsistentMapBuilder()
@@ -118,7 +129,7 @@
 
         portChainStore.put(portChain.portChainId(), portChain);
         if (!portChainStore.containsKey(portChain.portChainId())) {
-            log.debug("The portChain is created failed which identifier was {}", portChain.portChainId()
+            log.error("The portChain created is failed which identifier was {}", portChain.portChainId()
                       .toString());
             return false;
         }
@@ -128,18 +139,20 @@
     @Override
     public boolean updatePortChain(PortChain portChain) {
         checkNotNull(portChain, PORT_CHAIN_NULL);
-
+        PortChain oldPortChain = null;
         if (!portChainStore.containsKey(portChain.portChainId())) {
-            log.debug("The portChain is not exist whose identifier was {} ",
-                      portChain.portChainId().toString());
+            log.warn("The portChain is not exist whose identifier was {} ",
+                     portChain.portChainId().toString());
             return false;
+        } else {
+            oldPortChain = portChainStore.get(portChain.portChainId());
         }
+        PortChain newPortChain = DefaultPortChain.create(portChain, oldPortChain);
+        portChainStore.put(newPortChain.portChainId(), newPortChain);
 
-        portChainStore.put(portChain.portChainId(), portChain);
-
-        if (!portChain.equals(portChainStore.get(portChain.portChainId()))) {
+        if (!newPortChain.equals(portChainStore.get(newPortChain.portChainId()))) {
             log.debug("The portChain is updated failed whose identifier was {} ",
-                      portChain.portChainId().toString());
+                      newPortChain.portChainId().toString());
             return false;
         }
         return true;
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java
index 2df0ee6..c769092 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchainsfmap/impl/PortChainSfMapManager.java
@@ -38,6 +38,7 @@
 import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
 import org.slf4j.Logger;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
 /**
@@ -86,13 +87,13 @@
         List<PortPairGroupId> portPairGrpList = portChain.portPairGroups();
         ListIterator<PortPairGroupId> listGrpIterator = portPairGrpList.listIterator();
 
-        while (listGrpIterator.next() != null) {
+        while (listGrpIterator.hasNext()) {
             PortPairGroupId portPairGroupId = listGrpIterator.next();
             PortPairGroup portPairGroup = portPairGroupService.getPortPairGroup(portPairGroupId);
             ServiceFunctionGroup sfg = new ServiceFunctionGroup(portPairGroup.name(), portPairGroup.description(),
                                                                 portPairGroup.portPairLoadMap());
             serviceFunctionGroupList.add(sfg);
         }
-        return serviceFunctionGroupList;
+        return ImmutableList.copyOf(serviceFunctionGroupList);
     }
 }
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
index 4547764..18105b2 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
@@ -19,6 +19,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.Collections;
+import java.util.UUID;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -35,8 +36,10 @@
 import org.onosproject.store.service.MultiValuedTimestamp;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultPortPair;
 import org.onosproject.vtnrsc.PortPair;
 import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
 import org.onosproject.vtnrsc.portpair.PortPairEvent;
 import org.onosproject.vtnrsc.portpair.PortPairListener;
 import org.onosproject.vtnrsc.portpair.PortPairService;
@@ -72,7 +75,7 @@
         KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
                 .register(KryoNamespaces.API)
                 .register(MultiValuedTimestamp.class)
-                .register(PortPair.class);
+                .register(PortPair.class, PortPairId.class, UUID.class, DefaultPortPair.class, TenantId.class);
 
         portPairStore = storageService.<PortPairId, PortPair>eventuallyConsistentMapBuilder()
                 .withName("portpairstore")
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
index eca172c..7ef6999 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
@@ -19,6 +19,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.Collections;
+import java.util.UUID;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -35,8 +36,11 @@
 import org.onosproject.store.service.MultiValuedTimestamp;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultPortPairGroup;
 import org.onosproject.vtnrsc.PortPairGroup;
 import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
 import org.onosproject.vtnrsc.portpairgroup.PortPairGroupEvent;
 import org.onosproject.vtnrsc.portpairgroup.PortPairGroupListener;
 import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
@@ -71,7 +75,8 @@
         KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
                 .register(KryoNamespaces.API)
                 .register(MultiValuedTimestamp.class)
-                .register(PortPairGroup.class);
+                .register(PortPairGroup.class, PortPairGroupId.class, UUID.class, DefaultPortPairGroup.class,
+                          TenantId.class, PortPairId.class);
 
         portPairGroupStore = storageService
                 .<PortPairGroupId, PortPairGroup>eventuallyConsistentMapBuilder()