ONOS-3345 Add processing about Instruction type Extention in
GroupModBuider.

Change-Id: I1c99db1c3c1105924ee7c6e2da31daa02f5a1af4
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java
index d5804f4..83abf37 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java
@@ -15,11 +15,25 @@
  */
 package org.onosproject.provider.of.group.impl;
 
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip6Address;
 import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
@@ -28,6 +42,7 @@
 import org.onosproject.net.group.GroupBucket;
 import org.onosproject.net.group.GroupBuckets;
 import org.onosproject.net.group.GroupDescription;
+import org.onosproject.openflow.controller.ExtensionInterpreter;
 import org.projectfloodlight.openflow.protocol.OFBucket;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFGroupAdd;
@@ -52,14 +67,6 @@
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.slf4j.Logger;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Optional;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
 /*
  * Builder for GroupMod.
  */
@@ -70,6 +77,7 @@
     private GroupDescription.Type type;
     private OFFactory factory;
     private Long xid;
+    private Optional<DriverService> driverService;
 
     private final Logger log = getLogger(getClass());
 
@@ -85,6 +93,16 @@
         this.xid = xid.orElse((long) 0);
     }
 
+    private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
+                            GroupDescription.Type type, OFFactory factory,
+                            Optional<Long> xid, Optional<DriverService> driverService) {
+       this.buckets = buckets;
+       this.groupId = groupId;
+       this.type = type;
+       this.factory = factory;
+       this.xid = xid.orElse((long) 0);
+       this.driverService = driverService;
+   }
     /**
      * Creates a builder for GroupMod.
      *
@@ -103,6 +121,24 @@
     }
 
     /**
+     * Creates a builder for GroupMod.
+     *
+     * @param buckets GroupBuckets object
+     * @param groupId Group Id to create
+     * @param type Group type
+     * @param factory OFFactory object
+     * @param xid transaction ID
+     * @param driverService driver Service
+     * @return GroupModBuilder object
+     */
+    public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
+                                          GroupDescription.Type type, OFFactory factory,
+                                          Optional<Long> xid, Optional<DriverService> driverService) {
+
+        return new GroupModBuilder(buckets, groupId, type, factory, xid, driverService);
+    }
+
+    /**
      * Builds the GroupAdd OF message.
      *
      * @return GroupAdd OF message
@@ -218,6 +254,12 @@
                             .setGroup(OFGroup.of(grp.groupId().id()));
                     actions.add(actgrp.build());
                     break;
+                case EXTENSION:
+                    Instructions.ExtensionInstructionWrapper wrapper =
+                    (Instructions.ExtensionInstructionWrapper) i;
+                    actions.add(buildExtensionAction(
+                            wrapper.extensionInstruction(), wrapper.deviceId()));
+                    break;
                 default:
                     log.warn("Instruction type {} not yet implemented.", i.type());
             }
@@ -372,5 +414,21 @@
         }
         return null;
     }
+
+    private OFAction buildExtensionAction(ExtensionInstruction i, DeviceId deviceId) {
+        if (!driverService.isPresent()) {
+            log.error("No driver service present");
+            return null;
+        }
+        Driver driver = driverService.get().getDriver(deviceId);
+        if (driver.hasBehaviour(ExtensionInterpreter.class)) {
+            DefaultDriverHandler handler =
+                    new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
+            ExtensionInterpreter interpreter = handler.behaviour(ExtensionInterpreter.class);
+            return interpreter.mapInstruction(factory, i);
+        }
+
+        return null;
+    }
 }
 
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index 5783c84..89c4692 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -16,7 +16,12 @@
 
 package org.onosproject.provider.of.group.impl;
 
-import com.google.common.collect.Maps;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -26,6 +31,7 @@
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.group.DefaultGroup;
 import org.onosproject.net.group.Group;
 import org.onosproject.net.group.GroupBuckets;
@@ -60,12 +66,7 @@
 import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.slf4j.Logger;
 
-import java.util.Collection;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicLong;
-
-import static org.slf4j.LoggerFactory.getLogger;
+import com.google.common.collect.Maps;
 
 /**
  * Provider which uses an OpenFlow controller to handle Group.
@@ -81,6 +82,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected GroupProviderRegistry providerRegistry;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+
     private GroupProviderService providerService;
 
     static final int POLL_INTERVAL = 10;
@@ -139,12 +143,21 @@
                 return;
             }
             final Long groupModXid = XID_COUNTER.getAndIncrement();
-            GroupModBuilder builder =
-                    GroupModBuilder.builder(groupOperation.buckets(),
-                            groupOperation.groupId(),
-                            groupOperation.groupType(),
-                            sw.factory(),
-                            Optional.of(groupModXid));
+            GroupModBuilder builder = null;
+            if (driverService == null) {
+                builder = GroupModBuilder.builder(groupOperation.buckets(),
+                                                groupOperation.groupId(),
+                                                groupOperation.groupType(),
+                                                sw.factory(),
+                                                Optional.of(groupModXid));
+            } else {
+                builder = GroupModBuilder.builder(groupOperation.buckets(),
+                                                  groupOperation.groupId(),
+                                                  groupOperation.groupType(),
+                                                  sw.factory(),
+                                                  Optional.of(groupModXid),
+                                                  Optional.of(driverService));
+            }
             OFGroupMod groupMod = null;
             switch (groupOperation.opType()) {
                 case ADD: