[ONOS-2860] ONOSFW L3 uses ARP table as arp proxy. It need modify ARP
request packet to response packet. OpenFlow protocol provides some
extension action to support it. e.g. move and load. But for now OpenFlow
java implementation doesn't support for them.

Change-Id: I8ee6b415d9dce9a471ad5b6d788eebc905219d89
diff --git a/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
index a746078..923dcde 100644
--- a/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
+++ b/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
@@ -25,6 +25,9 @@
 import org.projectfloodlight.openflow.protocol.OFActionType;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
+import org.projectfloodlight.openflow.protocol.action.OFActionNicira;
+import org.projectfloodlight.openflow.protocol.action.OFActionNiciraMove;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
@@ -36,6 +39,13 @@
 public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviour
         implements ExtensionTreatmentInterpreter, ExtensionTreatmentResolver {
 
+    private static final int TYPE_NICIRA = 0x2320;
+    private static final int SUB_TYPE_MOVE = 6;
+    private static final int SRC_ARP_SHA = 0x00012206;
+    private static final int SRC_ARP_SPA = 0x00002004;
+    private static final int SRC_ETH = 0x00000406;
+    private static final int SRC_IP = 0x00000e04;
+
     @Override
     public boolean supported(ExtensionTreatmentType extensionTreatmentType) {
         if (extensionTreatmentType.equals(
@@ -129,11 +139,19 @@
             NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
             return factory.actions().niciraSetNshc4(niciraNshch.nshCh().nshContextHeader());
         }
-        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())
                 || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())
                 || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
                 || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
-           // TODO this will be implemented later
+            MoveExtensionTreatment mov = (MoveExtensionTreatment) extensionTreatment;
+            OFActionNiciraMove.Builder action = factory.actions()
+                    .buildNiciraMove();
+            action.setDstOfs(mov.dstOffset());
+            action.setSrcOfs(mov.srcOffset());
+            action.setNBits(mov.nBits());
+            action.setSrc(mov.src());
+            action.setDst(mov.dst());
+            return action.build();
         }
         return null;
     }
@@ -152,6 +170,34 @@
                         "Driver does not support extension type " + oxm.getMatchField().id);
             }
         }
+        if (action.getType().equals(OFActionType.EXPERIMENTER)) {
+            OFActionExperimenter experimenter = (OFActionExperimenter) action;
+            if (Long.valueOf(experimenter.getExperimenter())
+                    .intValue() == TYPE_NICIRA) {
+                OFActionNicira nicira = (OFActionNicira) experimenter;
+                if (nicira.getSubtype() == SUB_TYPE_MOVE) {
+                    OFActionNiciraMove moveAction = (OFActionNiciraMove) nicira;
+                    switch (Long.valueOf(moveAction.getSrc()).intValue()) {
+                    case SRC_ARP_SHA:
+                        return NiciraMoveTreatmentFactory
+                                .createNiciraMovArpShaToTha();
+                    case SRC_ETH:
+                        return NiciraMoveTreatmentFactory
+                                .createNiciraMovEthSrcToDst();
+                    case SRC_IP:
+                        return NiciraMoveTreatmentFactory
+                                .createNiciraMovIpSrcToDst();
+                    case SRC_ARP_SPA:
+                        return NiciraMoveTreatmentFactory
+                                .createNiciraMovArpSpaToTpa();
+                    default:
+                        throw new UnsupportedOperationException("Driver does not support move from "
+                                + moveAction.getSrc() + " to "
+                                + moveAction.getDst());
+                    }
+                }
+            }
+        }
         return null;
     }
 
diff --git a/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java b/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
index ac42a3b..c7b00be 100644
--- a/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
+++ b/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
@@ -91,7 +91,7 @@
         int dstOfs = 0;
         int nBits = 32;
         int srcIp = 0x00000e04;
-        int dstIp = 0x00001006;
+        int dstIp = 0x00001004;
         return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcIp,
                                                  dstIp,
                                                  ExtensionTreatmentType.ExtensionTreatmentTypes
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index b1fa717..e78b4f1 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -329,6 +329,14 @@
                         OFActionCircuit ct = (OFActionCircuit) exp;
                         short lambda = ((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber();
                         builder.add(Instructions.modL0Lambda(Lambda.indexedLambda(lambda)));
+                    }  else if (exp.getExperimenter() == 0x2320) {
+                        DriverHandler driver = getDriver(dpid);
+                        ExtensionTreatmentInterpreter interpreter = driver
+                                .behaviour(ExtensionTreatmentInterpreter.class);
+                        if (interpreter != null) {
+                            builder.extension(interpreter.mapAction(exp),
+                                              DeviceId.deviceId(Dpid.uri(dpid)));
+                        }
                     } else {
                         log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
                     }