Fix group handler in CpqD OFDPA driver

We should not use OFDPA extension VLAN ID in CpqD OFDPA driver (gerrit#8609)

Change-Id: Ife451c25c48a7aba2c4f7f8c66f71c9f362ab37c
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2GroupHandler.java
new file mode 100644
index 0000000..39fba4f
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2GroupHandler.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.driver.pipeline;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupKey;
+import org.slf4j.Logger;
+
+import java.util.Collections;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Group handler for CpqD OFDPA pipeline.
+ */
+public class CpqdOfdpa2GroupHandler extends Ofdpa2GroupHandler {
+    private final Logger log = getLogger(getClass());
+
+    @Override
+    protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
+                                      ApplicationId appId, boolean mpls,
+                                      TrafficSelector meta) {
+        // for the l2interface group, get vlan and port info
+        // for the outer group, get the src/dst mac, and vlan info
+        TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder();
+        TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
+        VlanId vlanid = null;
+        long portNum = 0;
+        boolean setVlan = false, popVlan = false;
+        MacAddress srcMac = MacAddress.ZERO;
+        MacAddress dstMac = MacAddress.ZERO;
+        for (Instruction ins : treatment.allInstructions()) {
+            if (ins.type() == Instruction.Type.L2MODIFICATION) {
+                L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
+                switch (l2ins.subtype()) {
+                    case ETH_DST:
+                        dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
+                        outerTtb.setEthDst(dstMac);
+                        break;
+                    case ETH_SRC:
+                        srcMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
+                        outerTtb.setEthSrc(srcMac);
+                        break;
+                    case VLAN_ID:
+                        vlanid = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId();
+                        outerTtb.setVlanId(vlanid);
+                        setVlan = true;
+                        break;
+                    case VLAN_POP:
+                        innerTtb.popVlan();
+                        popVlan = true;
+                        break;
+                    case DEC_MPLS_TTL:
+                    case MPLS_LABEL:
+                    case MPLS_POP:
+                    case MPLS_PUSH:
+                    case VLAN_PCP:
+                    case VLAN_PUSH:
+                    default:
+                        break;
+                }
+            } else if (ins.type() == Instruction.Type.OUTPUT) {
+                portNum = ((Instructions.OutputInstruction) ins).port().toLong();
+                innerTtb.add(ins);
+            } else {
+                log.warn("Driver does not handle this type of TrafficTreatment"
+                        + " instruction in nextObjectives:  {}", ins.type());
+            }
+        }
+
+        if (vlanid == null && meta != null) {
+            // use metadata if available
+            Criterion vidCriterion = meta.getCriterion(Criterion.Type.VLAN_VID);
+            if (vidCriterion != null) {
+                vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
+            }
+            // if vlan is not set, use the vlan in metadata for outerTtb
+            if (vlanid != null && !setVlan) {
+                outerTtb.setVlanId(vlanid);
+            }
+        }
+
+        if (vlanid == null) {
+            log.error("Driver cannot process an L2/L3 group chain without "
+                            + "egress vlan information for dev: {} port:{}",
+                    deviceId, portNum);
+            return null;
+        }
+
+        if (!setVlan && !popVlan) {
+            // untagged outgoing port
+            TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
+            temp.popVlan();
+            innerTtb.build().allInstructions().forEach(i -> temp.add(i));
+            innerTtb = temp;
+        }
+
+        // assemble information for ofdpa l2interface group
+        int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) portNum;
+        // a globally unique groupkey that is different for ports in the same device,
+        // but different for the same portnumber on different devices. Also different
+        // for the various group-types created out of the same next objective.
+        int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum);
+        final GroupKey l2groupkey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(l2gk));
+
+        // assemble information for outer group
+        GroupDescription outerGrpDesc = null;
+        if (mpls) {
+            // outer group is MPLSInteface
+            int mplsInterfaceIndex = getNextAvailableIndex();
+            int mplsgroupId = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & mplsInterfaceIndex);
+            final GroupKey mplsgroupkey = new DefaultGroupKey(
+                               Ofdpa2Pipeline.appKryo.serialize(mplsInterfaceIndex));
+            outerTtb.group(new DefaultGroupId(l2groupId));
+            // create the mpls-interface group description to wait for the
+            // l2 interface group to be processed
+            GroupBucket mplsinterfaceGroupBucket =
+                    DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
+            outerGrpDesc = new DefaultGroupDescription(
+                    deviceId,
+                    GroupDescription.Type.INDIRECT,
+                    new GroupBuckets(Collections.singletonList(
+                            mplsinterfaceGroupBucket)),
+                    mplsgroupkey,
+                    mplsgroupId,
+                    appId);
+            log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}",
+                    deviceId, Integer.toHexString(mplsgroupId),
+                    mplsgroupkey, nextId);
+        } else {
+            // outer group is L3Unicast
+            int l3unicastIndex = getNextAvailableIndex();
+            int l3groupId = L3_UNICAST_TYPE | (TYPE_MASK & l3unicastIndex);
+            final GroupKey l3groupkey = new DefaultGroupKey(
+                               Ofdpa2Pipeline.appKryo.serialize(l3unicastIndex));
+            outerTtb.group(new DefaultGroupId(l2groupId));
+            // create the l3unicast group description to wait for the
+            // l2 interface group to be processed
+            GroupBucket l3unicastGroupBucket =
+                    DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build());
+            outerGrpDesc = new DefaultGroupDescription(
+                    deviceId,
+                    GroupDescription.Type.INDIRECT,
+                    new GroupBuckets(Collections.singletonList(
+                            l3unicastGroupBucket)),
+                    l3groupkey,
+                    l3groupId,
+                    appId);
+            log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}",
+                    deviceId, Integer.toHexString(l3groupId),
+                    l3groupkey, nextId);
+        }
+
+        // store l2groupkey with the groupChainElem for the outer-group that depends on it
+        GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1, false);
+        updatePendingGroups(l2groupkey, gce);
+
+        // create group description for the inner l2interfacegroup
+        GroupBucket l2InterfaceGroupBucket =
+                DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build());
+        GroupDescription l2groupDescription =
+                new DefaultGroupDescription(
+                        deviceId,
+                        GroupDescription.Type.INDIRECT,
+                        new GroupBuckets(Collections.singletonList(
+                                l2InterfaceGroupBucket)),
+                        l2groupkey,
+                        l2groupId,
+                        appId);
+        log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}",
+                deviceId, Integer.toHexString(l2groupId),
+                l2groupkey, nextId);
+        return new GroupInfo(l2groupDescription, outerGrpDesc);
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2Pipeline.java
index 568a1c2..6bcebd7 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2Pipeline.java
@@ -32,15 +32,20 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.NextGroup;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.DefaultFlowRule;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.Criteria;
@@ -60,6 +65,7 @@
 import org.onosproject.net.flowobjective.ObjectiveError;
 import org.onosproject.net.group.Group;
 import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupService;
 import org.slf4j.Logger;
 
 
@@ -75,6 +81,27 @@
 
     private final Logger log = getLogger(getClass());
 
+    @Override
+    public void init(DeviceId deviceId, PipelinerContext context) {
+        this.deviceId = deviceId;
+
+        // Initialize OFDPA group handler
+        groupHandler = new CpqdOfdpa2GroupHandler();
+        groupHandler.init(deviceId, context);
+
+        serviceDirectory = context.directory();
+        coreService = serviceDirectory.get(CoreService.class);
+        flowRuleService = serviceDirectory.get(FlowRuleService.class);
+        groupService = serviceDirectory.get(GroupService.class);
+        flowObjectiveStore = context.store();
+        deviceService = serviceDirectory.get(DeviceService.class);
+
+        driverId = coreService.registerApplication(
+                "org.onosproject.driver.CpqdOfdpa2Pipeline");
+
+        initializePipeline();
+    }
+
     /*
      * CPQD emulation does not require special untagged packet handling, unlike
      * the real ofdpa.
@@ -253,13 +280,13 @@
 
         for (PortNumber pnum : portnums) {
             // update storage
-            ofdpa2GroupHandler.port2Vlan.put(pnum, storeVlan);
-            Set<PortNumber> vlanPorts = ofdpa2GroupHandler.vlan2Port.get(storeVlan);
+            groupHandler.port2Vlan.put(pnum, storeVlan);
+            Set<PortNumber> vlanPorts = groupHandler.vlan2Port.get(storeVlan);
             if (vlanPorts == null) {
                 vlanPorts = Collections.newSetFromMap(
                                     new ConcurrentHashMap<PortNumber, Boolean>());
                 vlanPorts.add(pnum);
-                ofdpa2GroupHandler.vlan2Port.put(storeVlan, vlanPorts);
+                groupHandler.vlan2Port.put(storeVlan, vlanPorts);
             } else {
                 vlanPorts.add(pnum);
             }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2VlanPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2VlanPipeline.java
index fa8b5ca..09fae88 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2VlanPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOfdpa2VlanPipeline.java
@@ -25,13 +25,18 @@
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.NextGroup;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.DefaultFlowRule;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.Criteria;
@@ -46,6 +51,7 @@
 import org.onosproject.net.flowobjective.ObjectiveError;
 import org.onosproject.net.group.Group;
 import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupService;
 import org.slf4j.Logger;
 
 
@@ -63,6 +69,27 @@
 
     private final Logger log = getLogger(getClass());
 
+    @Override
+    public void init(DeviceId deviceId, PipelinerContext context) {
+        this.deviceId = deviceId;
+
+        // Initialize OFDPA group handler
+        groupHandler = new CpqdOfdpa2GroupHandler();
+        groupHandler.init(deviceId, context);
+
+        serviceDirectory = context.directory();
+        coreService = serviceDirectory.get(CoreService.class);
+        flowRuleService = serviceDirectory.get(FlowRuleService.class);
+        groupService = serviceDirectory.get(GroupService.class);
+        flowObjectiveStore = context.store();
+        deviceService = serviceDirectory.get(DeviceService.class);
+
+        driverId = coreService.registerApplication(
+                "org.onosproject.driver.CpqdOfdpa2VlanPipeline");
+
+        initializePipeline();
+    }
+
     /*
      * Cpqd emulation does not handle vlan tags and mpls labels correctly.
      * Since this driver does not deal with MPLS, there is no need for
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
index 8a01f17..9c3c9eb 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
@@ -92,28 +92,28 @@
      * L2 Flood Groups have <4bits-4><12bits-vlanid><16bits-index>
      * L3 VPN Groups have <4bits-9><4bits-2><24bits-index>
      */
-    private static final int L2_INTERFACE_TYPE = 0x00000000;
-    private static final int L3_INTERFACE_TYPE = 0x50000000;
-    private static final int L3_UNICAST_TYPE = 0x20000000;
-    private static final int L3_MULTICAST_TYPE = 0x60000000;
-    private static final int MPLS_INTERFACE_TYPE = 0x90000000;
-    private static final int MPLS_L3VPN_SUBTYPE = 0x92000000;
-    private static final int L3_ECMP_TYPE = 0x70000000;
-    private static final int L2_FLOOD_TYPE = 0x40000000;
+    protected static final int L2_INTERFACE_TYPE = 0x00000000;
+    protected static final int L3_INTERFACE_TYPE = 0x50000000;
+    protected static final int L3_UNICAST_TYPE = 0x20000000;
+    protected static final int L3_MULTICAST_TYPE = 0x60000000;
+    protected static final int MPLS_INTERFACE_TYPE = 0x90000000;
+    protected static final int MPLS_L3VPN_SUBTYPE = 0x92000000;
+    protected static final int L3_ECMP_TYPE = 0x70000000;
+    protected static final int L2_FLOOD_TYPE = 0x40000000;
 
-    private static final int TYPE_MASK = 0x0fffffff;
-    private static final int SUBTYPE_MASK = 0x00ffffff;
-    private static final int TYPE_VLAN_MASK = 0x0000ffff;
+    protected static final int TYPE_MASK = 0x0fffffff;
+    protected static final int SUBTYPE_MASK = 0x00ffffff;
+    protected static final int TYPE_VLAN_MASK = 0x0000ffff;
 
-    private static final int PORT_LOWER_BITS_MASK = 0x3f;
-    private static final long PORT_HIGHER_BITS_MASK = ~PORT_LOWER_BITS_MASK;
+    protected static final int PORT_LOWER_BITS_MASK = 0x3f;
+    protected static final long PORT_HIGHER_BITS_MASK = ~PORT_LOWER_BITS_MASK;
 
     private final Logger log = getLogger(getClass());
     private ServiceDirectory serviceDirectory;
     protected GroupService groupService;
     protected StorageService storageService;
 
-    private DeviceId deviceId;
+    protected DeviceId deviceId;
     private FlowObjectiveStore flowObjectiveStore;
     private Cache<GroupKey, List<OfdpaNextGroup>> pendingNextObjectives;
     private ConcurrentHashMap<GroupKey, Set<GroupChainElem>> pendingGroups;
@@ -282,8 +282,8 @@
     /**
      * Creates one of two possible group-chains from the treatment
      * passed in. Depending on the MPLS boolean, this method either creates
-     * an L3Unicast Group --> L2Interface Group, if mpls is false;
-     * or MPLSInterface Group --> L2Interface Group, if mpls is true;
+     * an L3Unicast Group --&gt; L2Interface Group, if mpls is false;
+     * or MPLSInterface Group --&gt; L2Interface Group, if mpls is true;
      * The returned 'inner' group description is always the L2 Interface group.
      *
      * @param treatment that needs to be broken up to create the group chain
@@ -296,7 +296,7 @@
      *         L3Unicast/MPLSInterface group. May return null if there is an
      *         error in processing the chain
      */
-    private GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
+    protected GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId,
                                       ApplicationId appId, boolean mpls,
                                       TrafficSelector meta) {
         // for the l2interface group, get vlan and port info
@@ -1039,7 +1039,7 @@
         }
     }
 
-    private void updatePendingGroups(GroupKey gkey, GroupChainElem gce) {
+    protected void updatePendingGroups(GroupKey gkey, GroupChainElem gce) {
         Set<GroupChainElem> gceSet = Collections.newSetFromMap(
                 new ConcurrentHashMap<GroupChainElem, Boolean>());
         gceSet.add(gce);
@@ -1145,7 +1145,7 @@
         }
     }
 
-    private int getNextAvailableIndex() {
+    protected int getNextAvailableIndex() {
         return (int) nextIndex.incrementAndGet();
     }
 
@@ -1160,7 +1160,7 @@
      * @param portNumber Port number
      * @return L2 interface group key
      */
-    private int l2InterfaceGroupKey(
+    protected int l2InterfaceGroupKey(
             DeviceId deviceId, VlanId vlanId, long portNumber) {
         int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
         long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
@@ -1171,7 +1171,7 @@
     /**
      * Utility class for moving group information around.
      */
-    private class GroupInfo {
+    protected class GroupInfo {
         /**
          * Description of the inner-most group of the group chain.
          * It is always an L2 interface group.
@@ -1240,7 +1240,7 @@
      * class are meant to be temporary and live as long as it is needed to wait for
      * preceding groups in the group chain to be created.
      */
-    private class GroupChainElem {
+    protected class GroupChainElem {
         private GroupDescription groupDescription;
         private AtomicInteger waitOnGroups;
         private boolean addBucketToGroup;
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
index dd48fe7..be35026 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2Pipeline.java
@@ -108,9 +108,9 @@
     protected static final int LOWEST_PRIORITY = 0x0;
 
     private final Logger log = getLogger(getClass());
-    private ServiceDirectory serviceDirectory;
+    protected ServiceDirectory serviceDirectory;
     protected FlowRuleService flowRuleService;
-    private CoreService coreService;
+    protected CoreService coreService;
     protected GroupService groupService;
     protected FlowObjectiveStore flowObjectiveStore;
     protected DeviceId deviceId;
@@ -125,20 +125,20 @@
         .register(ArrayDeque.class)
         .build();
 
-    protected Ofdpa2GroupHandler ofdpa2GroupHandler;
+    protected Ofdpa2GroupHandler groupHandler;
 
     protected Set<IPCriterion> sentIpFilters = Collections.newSetFromMap(
                                                new ConcurrentHashMap<>());
 
     @Override
     public void init(DeviceId deviceId, PipelinerContext context) {
-        this.serviceDirectory = context.directory();
         this.deviceId = deviceId;
 
         // Initialize OFDPA group handler
-        ofdpa2GroupHandler = new Ofdpa2GroupHandler();
-        ofdpa2GroupHandler.init(deviceId, context);
+        groupHandler = new Ofdpa2GroupHandler();
+        groupHandler.init(deviceId, context);
 
+        serviceDirectory = context.directory();
         coreService = serviceDirectory.get(CoreService.class);
         flowRuleService = serviceDirectory.get(FlowRuleService.class);
         groupService = serviceDirectory.get(GroupService.class);
@@ -146,7 +146,7 @@
         deviceService = serviceDirectory.get(DeviceService.class);
 
         driverId = coreService.registerApplication(
-                "org.onosproject.driver.OFDPA2Pipeline");
+                "org.onosproject.driver.Ofdpa2Pipeline");
 
         initializePipeline();
     }
@@ -224,19 +224,19 @@
             }
             log.debug("Processing NextObjective id{} in dev{} - add group",
                       nextObjective.id(), deviceId);
-            ofdpa2GroupHandler.addGroup(nextObjective);
+            groupHandler.addGroup(nextObjective);
             break;
         case ADD_TO_EXISTING:
             if (nextGroup != null) {
                 log.debug("Processing NextObjective id{} in dev{} - add bucket",
                           nextObjective.id(), deviceId);
-                ofdpa2GroupHandler.addBucketToGroup(nextObjective, nextGroup);
+                groupHandler.addBucketToGroup(nextObjective, nextGroup);
             } else {
                 // it is possible that group-chain has not been fully created yet
                 log.debug("Waiting to add bucket to group for next-id:{} in dev:{}",
                           nextObjective.id(), deviceId);
                 // by design only one pending bucket is allowed for the group
-                ofdpa2GroupHandler.pendingBuckets.put(nextObjective.id(), nextObjective);
+                groupHandler.pendingBuckets.put(nextObjective.id(), nextObjective);
             }
             break;
         case REMOVE:
@@ -247,7 +247,7 @@
             }
             log.debug("Processing NextObjective id{}  in dev{} - remove group",
                       nextObjective.id(), deviceId);
-            ofdpa2GroupHandler.removeGroup(nextObjective, nextGroup);
+            groupHandler.removeGroup(nextObjective, nextGroup);
             break;
         case REMOVE_FROM_EXISTING:
             if (nextGroup == null) {
@@ -257,7 +257,7 @@
             }
             log.debug("Processing NextObjective id{} in dev{} - remove bucket",
                       nextObjective.id(), deviceId);
-            ofdpa2GroupHandler.removeBucketFromGroup(nextObjective, nextGroup);
+            groupHandler.removeBucketFromGroup(nextObjective, nextGroup);
             break;
         default:
             log.warn("Unsupported operation {}", nextObjective.op());
@@ -500,13 +500,13 @@
 
         for (PortNumber pnum : portnums) {
             // update storage
-            ofdpa2GroupHandler.port2Vlan.put(pnum, storeVlan);
-            Set<PortNumber> vlanPorts = ofdpa2GroupHandler.vlan2Port.get(storeVlan);
+            groupHandler.port2Vlan.put(pnum, storeVlan);
+            Set<PortNumber> vlanPorts = groupHandler.vlan2Port.get(storeVlan);
             if (vlanPorts == null) {
                 vlanPorts = Collections.newSetFromMap(
                                     new ConcurrentHashMap<PortNumber, Boolean>());
                 vlanPorts.add(pnum);
-                ofdpa2GroupHandler.vlan2Port.put(storeVlan, vlanPorts);
+                groupHandler.vlan2Port.put(storeVlan, vlanPorts);
             } else {
                 vlanPorts.add(pnum);
             }