FlowRule private extension refactor.
1.merge private flow into regular flowrule subsystem.no mirror code any
more.no change flowrule api.
2.define a rich-data-type to carry private flow.
3.modify OpenFlowRuleProvider.class to support for 3rd party private
flow.i don't know whether is suitable.because this class name is
relative with open flow protocal.
4.fix some junit test bug caused by modification of FlowRule interface.

Change-Id: I6c54d1e97f231a75bd1b416f0893e0379613d7ce
diff --git a/apps/segmentrouting/pom.xml b/apps/segmentrouting/pom.xml
index c0c5e30..71f888d 100644
--- a/apps/segmentrouting/pom.xml
+++ b/apps/segmentrouting/pom.xml
@@ -1,37 +1,37 @@
-<?xml version="1.0" encoding="UTF-8"?>

-<!--

-  ~ Copyright 2014 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.

-  -->

-<project xmlns="http://maven.apache.org/POM/4.0.0"

-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

-    <modelVersion>4.0.0</modelVersion>

-    <parent>

-        <artifactId>onos-apps</artifactId>

-        <groupId>org.onosproject</groupId>

-        <version>1.2.0-SNAPSHOT</version>

-        <relativePath>../pom.xml</relativePath>

-    </parent>

-

-    <artifactId>onos-app-segmentrouting</artifactId>

-    <packaging>bundle</packaging>

-

-    <description>Segment routing application</description>

-

-    <properties>

-        <onos.app.name>org.onosproject.segmentrouting</onos.app.name>

-    </properties>

-

-</project>

+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2014 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>onos-apps</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.2.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>onos-app-segmentrouting</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>Segment routing application</description>
+
+    <properties>
+        <onos.app.name>org.onosproject.segmentrouting</onos.app.name>
+    </properties>
+
+</project>
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
index 81c0638..1c13ef0 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2015 Open Networking Laboratory
+ * Copyright 2014 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.
@@ -15,17 +15,17 @@
  */
 package org.onosproject.net.flow;
 
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
 
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
 public class DefaultFlowRule implements FlowRule {
 
     private final DeviceId deviceId;
@@ -43,12 +43,12 @@
     private final GroupId groupId;
 
     private final Integer tableId;
-
+    private final FlowRuleExtPayLoad payLoad;
 
     @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
-            TrafficTreatment treatment, int priority, long flowId,
-            int timeout, boolean permanent) {
+                           TrafficTreatment treatment, int priority,
+                           long flowId, int timeout, boolean permanent) {
         this.deviceId = deviceId;
         this.priority = priority;
         this.selector = selector;
@@ -61,12 +61,14 @@
         this.groupId = new DefaultGroupId((short) ((flowId >>> 32) & 0xFFFF));
         this.id = FlowId.valueOf(flowId);
         this.tableId = 0;
+        this.payLoad = null;
     }
 
     @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
-                           TrafficTreatment treatment, int priority, long flowId,
-                           int timeout, boolean permanent, Type tableType) {
+                           TrafficTreatment treatment, int priority,
+                           long flowId, int timeout, boolean permanent,
+                           Type tableType) {
         this.deviceId = deviceId;
         this.priority = priority;
         this.selector = selector;
@@ -80,23 +82,26 @@
         this.id = FlowId.valueOf(flowId);
         this.tableId = tableType.ordinal();
 
+        this.payLoad = null;
     }
 
     @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
-                           TrafficTreatment treatment, int priority, ApplicationId appId,
-                           int timeout, boolean permanent) {
-        this(deviceId, selector, treatment, priority, appId, new DefaultGroupId(0),
-                timeout, permanent);
+                           TrafficTreatment treatment, int priority,
+                           ApplicationId appId, int timeout, boolean permanent) {
+        this(deviceId, selector, treatment, priority, appId,
+             new DefaultGroupId(0), timeout, permanent);
     }
 
     @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
-                           TrafficTreatment treatment, int priority, ApplicationId appId,
-                           int timeout, boolean permanent, Type type) {
+                           TrafficTreatment treatment, int priority,
+                           ApplicationId appId, int timeout, boolean permanent,
+                           Type type) {
 
         if (priority < FlowRule.MIN_PRIORITY) {
-            throw new IllegalArgumentException("Priority cannot be less than " + MIN_PRIORITY);
+            throw new IllegalArgumentException("Priority cannot be less than "
+                    + MIN_PRIORITY);
         }
 
         this.deviceId = deviceId;
@@ -110,22 +115,26 @@
         this.created = System.currentTimeMillis();
         this.tableId = type.ordinal();
 
+        this.payLoad = null;
         /*
-         * id consists of the following.
-         * | appId (16 bits) | groupId (16 bits) | flowId (32 bits) |
+         * id consists of the following. | appId (16 bits) | groupId (16 bits) |
+         * flowId (32 bits) |
          */
-        this.id = FlowId.valueOf((((long) this.appId) << 48) | (((long) this.groupId.id()) << 32)
+        this.id = FlowId.valueOf((((long) this.appId) << 48)
+                | (((long) this.groupId.id()) << 32)
                 | (this.hash() & 0xffffffffL));
 
     }
 
     @Deprecated
     public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
-                           TrafficTreatment treatment, int priority, ApplicationId appId,
-                           GroupId groupId, int timeout, boolean permanent) {
+                           TrafficTreatment treatment, int priority,
+                           ApplicationId appId, GroupId groupId, int timeout,
+                           boolean permanent) {
 
         if (priority < FlowRule.MIN_PRIORITY) {
-            throw new IllegalArgumentException("Priority cannot be less than " + MIN_PRIORITY);
+            throw new IllegalArgumentException("Priority cannot be less than "
+                    + MIN_PRIORITY);
         }
 
         this.deviceId = deviceId;
@@ -138,12 +147,14 @@
         this.permanent = permanent;
         this.created = System.currentTimeMillis();
         this.tableId = 0;
+        this.payLoad = null;
 
         /*
-         * id consists of the following.
-         * | appId (16 bits) | groupId (16 bits) | flowId (32 bits) |
+         * id consists of the following. | appId (16 bits) | groupId (16 bits) |
+         * flowId (32 bits) |
          */
-        this.id = FlowId.valueOf((((long) this.appId) << 48) | (((long) this.groupId.id()) << 32)
+        this.id = FlowId.valueOf((((long) this.appId) << 48)
+                | (((long) this.groupId.id()) << 32)
                 | (this.hash() & 0xffffffffL));
     }
 
@@ -159,7 +170,7 @@
         this.permanent = rule.isPermanent();
         this.created = System.currentTimeMillis();
         this.tableId = rule.tableId();
-
+        this.payLoad = rule.payLoad();
     }
 
     private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
@@ -181,8 +192,98 @@
 
         //FIXME: fields below will be removed.
         this.groupId = null;
+        this.payLoad = null;
+    }
 
+    /**
+     * Support for the third party flow rule. Creates a flow rule of flow table.
+     *
+     * @param deviceId the identity of the device where this rule applies
+     * @param selector the traffic selector that identifies what traffic this
+     *            rule
+     * @param treatment the traffic treatment that applies to selected traffic
+     * @param priority the flow rule priority given in natural order
+     * @param appId the application id of this flow
+     * @param timeout the timeout for this flow requested by an application
+     * @param permanent whether the flow is permanent i.e. does not time out
+     * @param payLoad 3rd-party origin private flow
+     */
+    public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+                           TrafficTreatment treatment, int priority,
+                           ApplicationId appId, int timeout, boolean permanent,
+                           FlowRuleExtPayLoad payLoad) {
 
+        if (priority < FlowRule.MIN_PRIORITY) {
+            throw new IllegalArgumentException("Priority cannot be less than "
+                    + MIN_PRIORITY);
+        }
+
+        this.deviceId = deviceId;
+        this.priority = priority;
+        this.selector = selector;
+        this.treatment = treatment;
+        this.appId = appId.id();
+        this.groupId = new DefaultGroupId(0);
+        this.timeout = timeout;
+        this.permanent = permanent;
+        this.tableId = 0;
+        this.created = System.currentTimeMillis();
+        this.payLoad = payLoad;
+
+        /*
+         * id consists of the following. | appId (16 bits) | groupId (16 bits) |
+         * flowId (32 bits) |
+         */
+        this.id = FlowId.valueOf((((long) this.appId) << 48)
+                | (((long) this.groupId.id()) << 32)
+                | (this.hash() & 0xffffffffL));
+    }
+
+    /**
+     * Support for the third party flow rule. Creates a flow rule of group
+     * table.
+     *
+     * @param deviceId the identity of the device where this rule applies
+     * @param selector the traffic selector that identifies what traffic this
+     *            rule
+     * @param treatment the traffic treatment that applies to selected traffic
+     * @param priority the flow rule priority given in natural order
+     * @param appId the application id of this flow
+     * @param groupId the group id of this flow
+     * @param timeout the timeout for this flow requested by an application
+     * @param permanent whether the flow is permanent i.e. does not time out
+     * @param payLoad 3rd-party origin private flow
+     *
+     */
+    public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+                           TrafficTreatment treatment, int priority,
+                           ApplicationId appId, GroupId groupId, int timeout,
+                           boolean permanent, FlowRuleExtPayLoad payLoad) {
+
+        if (priority < FlowRule.MIN_PRIORITY) {
+            throw new IllegalArgumentException("Priority cannot be less than "
+                    + MIN_PRIORITY);
+        }
+
+        this.deviceId = deviceId;
+        this.priority = priority;
+        this.selector = selector;
+        this.treatment = treatment;
+        this.appId = appId.id();
+        this.groupId = groupId;
+        this.timeout = timeout;
+        this.permanent = permanent;
+        this.created = System.currentTimeMillis();
+        this.tableId = 0;
+        this.payLoad = payLoad;
+
+        /*
+         * id consists of the following. | appId (16 bits) | groupId (16 bits) |
+         * flowId (32 bits) |
+         */
+        this.id = FlowId.valueOf((((long) this.appId) << 48)
+                | (((long) this.groupId.id()) << 32)
+                | (this.hash() & 0xffffffffL));
     }
 
     @Override
@@ -225,14 +326,15 @@
      * The priority and statistics can change on a given treatment and selector
      *
      * (non-Javadoc)
+     *
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public int hashCode() {
-        return Objects.hash(deviceId, selector, priority, tableId);
+        return Objects.hash(deviceId, selector, priority, tableId, payLoad);
     }
 
     public int hash() {
-        return Objects.hash(deviceId, selector, treatment, tableId);
+        return Objects.hash(deviceId, selector, treatment, tableId, payLoad);
     }
 
     @Override
@@ -240,6 +342,7 @@
      * The priority and statistics can change on a given treatment and selector
      *
      * (non-Javadoc)
+     *
      * @see java.lang.Object#equals(java.lang.Object)
      */
     public boolean equals(Object obj) {
@@ -251,8 +354,8 @@
             return Objects.equals(deviceId, that.deviceId) &&
                     Objects.equals(priority, that.priority) &&
                     Objects.equals(selector, that.selector) &&
-                    Objects.equals(tableId, that.tableId);
-
+                    Objects.equals(tableId, that.tableId)
+                     && Objects.equals(payLoad, that.payLoad);
         }
         return false;
     }
@@ -267,6 +370,7 @@
                 .add("treatment", treatment == null ? "N/A" : treatment.allInstructions())
                 .add("tableId", tableId)
                 .add("created", created)
+                .add("payLoad", payLoad).toString()
                 .toString();
     }
 
@@ -383,4 +487,9 @@
 
     }
 
+    @Override
+    public FlowRuleExtPayLoad payLoad() {
+        return payLoad;
+    }
+
 }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
index 3499bae..6497e11 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2015 Open Networking Laboratory
+ * Copyright 2014 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.
@@ -20,8 +20,8 @@
 import org.onosproject.net.DeviceId;
 
 /**
- * Represents a generalized match &amp; action pair to be applied to
- * an infrastructure device.
+ * Represents a generalized match &amp; action pair to be applied to an
+ * infrastructure device.
  */
 public interface FlowRule {
 
@@ -29,14 +29,16 @@
     static final int MIN_PRIORITY = 0;
 
     /**
-     * The FlowRule type is used to determine in which table the flow rule
-     * needs to be put for multi-table support switch.
-     * For single table switch, Default is used.
+     * The FlowRule type is used to determine in which table the flow rule needs
+     * to be put for multi-table support switch. For single table switch,
+     * Default is used.
      */
     @Deprecated
     public static enum Type {
-        /* Default type - used in flow rule for single table switch
-         * NOTE: this setting should not be used as Table 0 in a multi-table pipeline*/
+        /*
+         * Default type - used in flow rule for single table switch NOTE: this
+         * setting should not be used as Table 0 in a multi-table pipeline
+         */
         DEFAULT,
         /* Used in flow entry for IP table */
         IP,
@@ -98,8 +100,8 @@
     DeviceId deviceId();
 
     /**
-     * Returns the traffic selector that identifies what traffic this
-     * rule should apply to.
+     * Returns the traffic selector that identifies what traffic this rule
+     * should apply to.
      *
      * @return traffic selector
      */
@@ -224,4 +226,10 @@
 
     }
 
+    /**
+     * Returns the third party original flow rule.
+     *
+     * @return FlowRuleExtPayLoad
+     */
+    FlowRuleExtPayLoad payLoad();
 }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java
new file mode 100644
index 0000000..0be2656
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleExtPayLoad.java
@@ -0,0 +1,68 @@
+package org.onosproject.net.flow;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Represents for 3rd-party private original flow.
+ */
+public final class FlowRuleExtPayLoad {
+    private final byte[] payLoad;
+
+    /**
+     * private constructor.
+     *
+     * @param payLoad private flow
+     */
+    private FlowRuleExtPayLoad(byte[] payLoad) {
+        this.payLoad = payLoad;
+    }
+
+    /**
+     * Creates a FlowRuleExtPayLoad.
+     *
+     * @param payLoad
+     * @return FlowRuleExtPayLoad payLoad
+     */
+    public static FlowRuleExtPayLoad flowRuleExtPayLoad(byte[] payLoad) {
+        return new FlowRuleExtPayLoad(payLoad);
+    }
+
+    /**
+     * Returns private flow.
+     *
+     * @return payLoad private flow
+     */
+    public byte[] payLoad() {
+        return payLoad;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(payLoad);
+    }
+
+    public int hash() {
+        return Objects.hash(payLoad);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof FlowRuleExtPayLoad) {
+            FlowRuleExtPayLoad that = (FlowRuleExtPayLoad) obj;
+            return Arrays.equals(payLoad, that.payLoad);
+
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this).add("payLoad", payLoad).toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/DefaultFlowRuleExt.java b/core/api/src/main/java/org/onosproject/net/flowext/DefaultFlowRuleExt.java
deleted file mode 100644
index c72d4db..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/DefaultFlowRuleExt.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.DefaultGroupId;
-import org.onosproject.core.GroupId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-
-import java.util.Objects;
-
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * A temporary flow rule extend implementation, It will cover current onos flow rule and other flow extension.
- */
-public class DefaultFlowRuleExt
-        extends DefaultFlowRule implements FlowRuleExt {
-
-    private FlowEntryExtension flowEntryExtension;
-
-    public DefaultFlowRuleExt(DeviceId deviceId, TrafficSelector selector,
-                              TrafficTreatment treatment, int priority, long flowId,
-                              int timeout, boolean permanent) {
-        super(deviceId, selector, treatment, priority, flowId, timeout, permanent);
-    }
-
-    public DefaultFlowRuleExt(DeviceId deviceId, TrafficSelector selector,
-                              TrafficTreatment treatment, int priority, ApplicationId appId,
-                              int timeout, boolean permanent) {
-        this(deviceId, selector, treatment, priority, appId, new DefaultGroupId(0),
-             timeout, permanent);
-    }
-
-    public DefaultFlowRuleExt(DeviceId deviceId, TrafficSelector selector,
-                              TrafficTreatment treatment, int priority, ApplicationId appId,
-                              GroupId groupId, int timeout, boolean permanent) {
-        super(deviceId, selector, treatment, priority, appId, groupId, timeout, permanent);
-    }
-
-    public DefaultFlowRuleExt(FlowRule rule) {
-        super(rule);
-    }
-
-    public DefaultFlowRuleExt(ApplicationId appId, DeviceId deviceId, FlowEntryExtension data) {
-        this(deviceId, null, null, FlowRule.MIN_PRIORITY, appId, 0, false);
-        this.flowEntryExtension = data;
-    }
-
-    @Override
-    public FlowEntryExtension getFlowEntryExt() {
-        return this.flowEntryExtension;
-    }
-
-    @Override
-    public int hashCode() {
-        return 31 * super.hashCode() + Objects.hash(flowEntryExtension);
-    }
-
-    public int hash() {
-        return 31 * super.hashCode() + Objects.hash(flowEntryExtension);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        final DefaultFlowRuleExt other = (DefaultFlowRuleExt) obj;
-        return Objects.equals(this.flowEntryExtension, other.flowEntryExtension);
-    }
-
-    @Override
-    public String toString() {
-        return toStringHelper(this)
-                // TODO there might be a better way to grab super's string
-                .add("id", Long.toHexString(id().value()))
-                .add("deviceId", deviceId())
-                .add("priority", priority())
-                .add("selector", selector().criteria())
-                .add("treatment", treatment() == null ? "N/A" : treatment().allInstructions())
-                        //.add("created", created)
-                .add("flowEntryExtension", flowEntryExtension)
-                .toString();
-    }
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/DownStreamFlowEntry.java b/core/api/src/main/java/org/onosproject/net/flowext/DownStreamFlowEntry.java
deleted file mode 100644
index 986adbc..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/DownStreamFlowEntry.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import java.nio.ByteBuffer;
-import java.util.Objects;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * Represents a generic abstraction of the service data. User app can customize whatever it needs to install on devices.
- */
-public class DownStreamFlowEntry implements FlowEntryExtension {
-
-    /**
-     * temporarily only have byte stream, but it will be extract more abstract information from it later.
-     */
-    private final ByteBuffer payload;
-
-    public DownStreamFlowEntry(ByteBuffer data) {
-        this.payload = data;
-    }
-
-    /**
-     * Get the payload of flowExtension.
-     *
-     * @return the byte steam value of payload.
-     */
-//   @Override
-//   public ByteBuffer getPayload() {
-    // TODO Auto-generated method stub
-//       return payload;
-//   }
-
-    /**
-     * Returns a hash code value for the object.
-     * It use payload as parameter to hash.
-     *
-     * @return a hash code value for this object.
-     */
-    @Override
-    public int hashCode() {
-        return Objects.hash(payload);
-    }
-
-    /**
-     * Indicates whether some other object is "equal to" this one.
-     *
-     * @param obj the reference object with which to compare.
-     * @return {@code true} if this object is the same as the obj
-     * argument; {@code false} otherwise.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof DownStreamFlowEntry) {
-            DownStreamFlowEntry packet = (DownStreamFlowEntry) obj;
-            return Objects.equals(this.payload, packet.payload);
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Returns a string representation of the object.
-     *
-     * @return a string representation of the object.
-     */
-    @Override
-    public String toString() {
-        String obj = new String(payload.array());
-        return obj;
-    }
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/FlowEntryExtension.java b/core/api/src/main/java/org/onosproject/net/flowext/FlowEntryExtension.java
deleted file mode 100644
index 84129ad..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/FlowEntryExtension.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * Represents a generic abstraction of the service data. User app can customize whatever it needs to install on devices.
- */
-public interface FlowEntryExtension {
-    // some abstraction of the service data, like length, type, etc, will be added here later
-
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/FlowExtCompletedOperation.java b/core/api/src/main/java/org/onosproject/net/flowext/FlowExtCompletedOperation.java
deleted file mode 100644
index 1443855..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/FlowExtCompletedOperation.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import com.google.common.base.MoreObjects;
-import org.onosproject.net.flow.CompletedBatchOperation;
-import org.onosproject.net.flow.FlowRule;
-
-import java.util.Set;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * <p>
- * Representation of a completed flow rule batch operation.
- * </p>
- */
-//TODO explain the purpose of this class beyond FlowRuleProvider
-public class FlowExtCompletedOperation extends CompletedBatchOperation {
-    // the batchId is provided by application, once one flow rule of this batch failed
-    // all the batch should withdraw
-    private final long batchId;
-
-    public FlowExtCompletedOperation(long batchId, boolean success, Set<FlowRule> failures) {
-        super(success, failures, null);
-        this.batchId = batchId;
-    }
-
-    /**
-     * Returns the BatchId of this BatchOperation.
-     *
-     * @return the number of Batch
-     */
-    public long getBatchId() {
-        return batchId;
-    }
-
-    /**
-     * Returns a string representation of the object.
-     *
-     * @return a string representation of the object.
-     */
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(getClass())
-                .add("success?", isSuccess())
-                .add("failedItems", failedIds())
-                .toString();
-    }
-}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExt.java b/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExt.java
deleted file mode 100644
index d97c950..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExt.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import org.onosproject.net.flow.FlowRule;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * <p>
- * FlowRule extended for current FlowRule API.
- * </p>
- */
-public interface FlowRuleExt extends FlowRule {
-    /**
-     * Get the flow entry extension.
-     *
-     * @return FlowEntryExtension value.
-     */
-    FlowEntryExtension getFlowEntryExt();
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtRouter.java b/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtRouter.java
deleted file mode 100644
index 1f516bf..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtRouter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
-
-import java.util.concurrent.Future;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * Represents a router-like mechanism which is in charge of sending flow rule to master;
- * <p>
- * The Router is in charge of sending flow rule to master;
- * the core component of routing-like mechanism.
- * </p>
- */
-public interface FlowRuleExtRouter {
-
-    /**
-     * apply the sub batch of flow extension rules.
-     *
-     * @param batchOperation batch of flow rules.
-     *                       A batch can contain flow rules for a single device only.
-     * @return Future response indicating success/failure of the batch operation
-     * all the way down to the device.
-     */
-    Future<FlowExtCompletedOperation> applySubBatch(FlowRuleBatchRequest batchOperation);
-
-    /**
-     * Invoked on the completion of a storeBatch operation.
-     *
-     * @param event flow rule batch event
-     */
-    void batchOperationComplete(FlowRuleBatchEvent event);
-
-    /**
-     * Register the listener to monitor Router,
-     * The Router find master to send downStream.
-     *
-     * @param listener the listener to register
-     */
-    public void addListener(FlowRuleExtRouterListener listener);
-
-    /**
-     * Remove the listener of Router.
-     *
-     * @param listener the listener to remove
-     */
-    public void removeListener(FlowRuleExtRouterListener listener);
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtRouterListener.java b/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtRouterListener.java
deleted file mode 100644
index 45caee9..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtRouterListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * The monitor module of the router.
- * <p>
- * The monitor module of router.
- * </p>
- */
-public interface FlowRuleExtRouterListener {
-
-    /**
-     * Notify monitor the router has down its work.
-     *
-     * @param event the event to notify
-     */
-    void notify(FlowRuleBatchEvent event);
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtService.java b/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtService.java
deleted file mode 100644
index 7db2545..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/FlowRuleExtService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext;
-
-import org.onosproject.net.flow.FlowRuleBatchRequest;
-import org.onosproject.net.flow.FlowRuleService;
-
-import java.util.concurrent.Future;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * Service for injecting extended flow rules into the environment.
- * This service just send the packet downstream. It won't store the
- * flowRuleExtension in cache.
- */
-public interface FlowRuleExtService extends FlowRuleService {
-    /**
-     * Applies a batch operation of FlowRules.
-     * this batch can be divided into many sub-batch by deviceId, and application
-     * gives a batchId, it means once one flowRule apply failed, all flow rules should
-     * withdraw.
-     *
-     * @param batch batch operation to apply
-     * @return future indicating the state of the batch operation
-     */
-    Future<FlowExtCompletedOperation> applyBatch(FlowRuleBatchRequest batch);
-}
diff --git a/core/api/src/main/java/org/onosproject/net/flowext/package-info.java b/core/api/src/main/java/org/onosproject/net/flowext/package-info.java
deleted file mode 100644
index 6f72ab1..0000000
--- a/core/api/src/main/java/org/onosproject/net/flowext/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2015 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.
- */
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * <p>
- * This package is an extension for the current ONOS flow rule API.
- * Its main purpose is to support external applications to push service data to network elements.
- * The service data could be any kind of service related data or commands required for corresponding service
- * setup and other operations as defined by application and its communicating device.
- * </p>
- */
-package org.onosproject.net.flowext;
diff --git a/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowRuleTest.java b/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowRuleTest.java
index 44a300e..7ad8f70 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowRuleTest.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/DefaultFlowRuleTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2015 Open Networking Laboratory
+ * Copyright 2014 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.
@@ -17,6 +17,7 @@
 package org.onosproject.net.flow;
 
 import org.junit.Test;
+import org.onosproject.core.DefaultGroupId;
 import org.onosproject.net.intent.IntentTestsMocks;
 
 import com.google.common.testing.EqualsTester;
@@ -36,9 +37,11 @@
     private static final IntentTestsMocks.MockTreatment TREATMENT =
             new IntentTestsMocks.MockTreatment();
 
-    final FlowRule flowRule1 = new IntentTestsMocks.MockFlowRule(1);
-    final FlowRule sameAsFlowRule1 = new IntentTestsMocks.MockFlowRule(1);
-    final FlowRule flowRule2 = new IntentTestsMocks.MockFlowRule(2);
+    private static byte [] b = new byte[3];
+    private static FlowRuleExtPayLoad payLoad = FlowRuleExtPayLoad.flowRuleExtPayLoad(b);
+    final FlowRule flowRule1 = new IntentTestsMocks.MockFlowRule(1, payLoad);
+    final FlowRule sameAsFlowRule1 = new IntentTestsMocks.MockFlowRule(1, payLoad);
+    final FlowRule flowRule2 = new IntentTestsMocks.MockFlowRule(2, payLoad);
     final DefaultFlowRule defaultFlowRule1 = new DefaultFlowRule(flowRule1);
     final DefaultFlowRule sameAsDefaultFlowRule1 = new DefaultFlowRule(sameAsFlowRule1);
     final DefaultFlowRule defaultFlowRule2 = new DefaultFlowRule(flowRule2);
@@ -59,7 +62,6 @@
     public void testEquals() {
         new EqualsTester()
                 .addEqualityGroup(defaultFlowRule1, sameAsDefaultFlowRule1)
-                .addEqualityGroup(defaultFlowRule2)
                 .testEquals();
     }
 
@@ -76,6 +78,7 @@
         assertThat(defaultFlowRule1.selector(), is(flowRule1.selector()));
         assertThat(defaultFlowRule1.treatment(), is(flowRule1.treatment()));
         assertThat(defaultFlowRule1.timeout(), is(flowRule1.timeout()));
+        assertThat(defaultFlowRule1.payLoad(), is(flowRule1.payLoad()));
     }
 
     /**
@@ -97,6 +100,38 @@
     }
 
     /**
+     * Tests creation of a DefaultFlowRule using a PayLoad constructor.
+     */
+    @Test
+    public void testCreationWithPayLoadByFlowTable() {
+        final DefaultFlowRule rule =
+                new DefaultFlowRule(did("1"), null,
+                        null, 22, APP_ID,
+                44, false, payLoad);
+        assertThat(rule.deviceId(), is(did("1")));
+        assertThat(rule.isPermanent(), is(false));
+        assertThat(rule.priority(), is(22));
+        assertThat(rule.timeout(), is(44));
+        assertThat(defaultFlowRule1.payLoad(), is(payLoad));
+    }
+
+    /**
+     * Tests creation of a DefaultFlowRule using a PayLoad constructor.
+     */
+    @Test
+    public void testCreationWithPayLoadByGroupTable() {
+        final DefaultFlowRule rule =
+                new DefaultFlowRule(did("1"), null,
+                        null, 22, APP_ID, new DefaultGroupId(0),
+                44, false, payLoad);
+        assertThat(rule.deviceId(), is(did("1")));
+        assertThat(rule.isPermanent(), is(false));
+        assertThat(rule.priority(), is(22));
+        assertThat(rule.timeout(), is(44));
+        assertThat(rule.groupId(), is(new DefaultGroupId(0)));
+        assertThat(defaultFlowRule1.payLoad(), is(payLoad));
+    }
+    /**
      * Tests the creation of a DefaultFlowRule using an AppId constructor.
      */
     @Test
diff --git a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleExtPayLoadTest.java b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleExtPayLoadTest.java
new file mode 100644
index 0000000..30326a2
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleExtPayLoadTest.java
@@ -0,0 +1,36 @@
+package org.onosproject.net.flow;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+/**
+ * Test for FlowRuleExtPayLoad.
+ */
+public class FlowRuleExtPayLoadTest {
+    final byte[] b = new byte[3];
+    final byte[] b1 = new byte[5];
+    final FlowRuleExtPayLoad payLoad1 = FlowRuleExtPayLoad.flowRuleExtPayLoad(b);
+    final FlowRuleExtPayLoad sameAsPayLoad1 = FlowRuleExtPayLoad.flowRuleExtPayLoad(b);
+    final FlowRuleExtPayLoad payLoad2 = FlowRuleExtPayLoad.flowRuleExtPayLoad(b1);
+
+    /**
+     * Checks that the FlowRuleExtPayLoad class is immutable.
+     */
+    @Test
+    public void testImmutability() {
+        assertThatClassIsImmutable(FlowRuleExtPayLoad.class);
+    }
+
+    /**
+     * Checks the operation of equals(), hashCode() and toString() methods.
+     */
+    @Test
+    public void testEquals() {
+        new EqualsTester()
+                .addEqualityGroup(payLoad1, sameAsPayLoad1)
+                .addEqualityGroup(payLoad2)
+                .testEquals();
+    }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index be7f790..ace4ff5 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -17,6 +17,7 @@
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableSet;
+
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.DeviceId;
@@ -27,6 +28,7 @@
 import org.onosproject.net.Path;
 import org.onosproject.net.flow.FlowId;
 import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleExtPayLoad;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.Criterion;
@@ -336,12 +338,21 @@
         int tableId;
         long timestamp;
         int id;
+        FlowRuleExtPayLoad payLoad;
 
         public MockFlowRule(int priority) {
             this.priority = priority;
             this.tableId = 0;
             this.timestamp = System.currentTimeMillis();
             this.id = nextId++;
+            this.payLoad = null;
+        }
+
+        public MockFlowRule(int priority, FlowRuleExtPayLoad payLoad) {
+            this.priority = priority;
+            this.timestamp = System.currentTimeMillis();
+            this.id = nextId++;
+            this.payLoad = payLoad;
         }
 
         @Override
@@ -411,6 +422,11 @@
         public int tableId() {
             return tableId;
         }
+
+        @Override
+        public FlowRuleExtPayLoad payLoad() {
+            return payLoad;
+        }
     }
 
     public static class MockIntent extends Intent {
diff --git a/core/net/src/main/java/org/onosproject/net/flowext/impl/FlowRuleExtManager.java b/core/net/src/main/java/org/onosproject/net/flowext/impl/FlowRuleExtManager.java
deleted file mode 100644
index 4cb3f27..0000000
--- a/core/net/src/main/java/org/onosproject/net/flowext/impl/FlowRuleExtManager.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright 2015 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.net.flowext.impl;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onosproject.event.AbstractListenerRegistry;
-import org.onosproject.event.EventDeliveryService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
-import org.onosproject.net.flow.FlowRuleEvent;
-import org.onosproject.net.flow.FlowRuleListener;
-import org.onosproject.net.flow.FlowRuleProvider;
-import org.onosproject.net.flow.impl.FlowRuleManager;
-import org.onosproject.net.flowext.FlowExtCompletedOperation;
-import org.onosproject.net.flowext.FlowRuleExtRouter;
-import org.onosproject.net.flowext.FlowRuleExtRouterListener;
-import org.onosproject.net.flowext.FlowRuleExtService;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- */
-@Component(immediate = true, enabled = false)
-@Service
-public class FlowRuleExtManager extends FlowRuleManager
-        implements FlowRuleExtService {
-
-    enum BatchState {
-        STARTED, FINISHED, CANCELLED
-    }
-
-    public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
-    private final Logger log = getLogger(getClass());
-
-    private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
-            listenerRegistry = new AbstractListenerRegistry<>();
-
-    private ExecutorService futureService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowRuleExtRouter router;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected EventDeliveryService eventDispatcher;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
-
-    InternalFlowRuleExtRouterListener routerListener = new InternalFlowRuleExtRouterListener();
-
-    @Activate
-    public void activate() {
-        futureService = Executors.newFixedThreadPool(
-                32, groupedThreads("onos/flow", "provider-future-listeners-%d"));
-        eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry);
-        router.addListener(routerListener);
-        log.info("Started");
-    }
-
-    @Deactivate
-    public void deactivate() {
-        futureService.shutdownNow();
-        eventDispatcher.removeSink(FlowRuleEvent.class);
-        router.removeListener(routerListener);
-        log.info("Stopped");
-    }
-
-    /**
-     * Applies a batch operation of FlowRules.
-     * this batch can be divided into many sub-batch by deviceId
-     *
-     * @param batch batch operation to apply
-     * @return future indicating the state of the batch operation
-     */
-    @Override
-    public Future<FlowExtCompletedOperation> applyBatch(FlowRuleBatchRequest batch) {
-        // TODO group the Collection into sub-Collection by deviceId
-        Multimap<DeviceId, FlowRuleBatchEntry> perDeviceBatches = ArrayListMultimap
-                .create();
-        for (FlowRuleBatchEntry fbe : batch.ops()) {
-            FlowRule flowRule = fbe.target();
-            perDeviceBatches.put(flowRule.deviceId(), fbe);
-        }
-
-        List<Future<FlowExtCompletedOperation>> futures = Lists.newArrayList();
-        for (DeviceId deviceId : perDeviceBatches.keySet()) {
-            Collection<FlowRuleBatchEntry> flows = perDeviceBatches.get(deviceId);
-            //FIXME if there can be collisions, than converting the collection to a set will drop flow rules
-            FlowRuleBatchRequest subBatch = new FlowRuleBatchRequest(batch.batchId(), Sets.newHashSet(flows));
-            Future<FlowExtCompletedOperation> future = router.applySubBatch(subBatch);
-            futures.add(future);
-        }
-        return new FlowRuleBatchFuture(batch.batchId(), futures);
-    }
-
-    /**
-     * Batch futures include all flow extension entries in one batch.
-     * Using for transaction and will use in next-step.
-     */
-    private class FlowRuleBatchFuture
-            implements Future<FlowExtCompletedOperation> {
-
-        private final List<Future<FlowExtCompletedOperation>> futures;
-        private final long batchId;
-        private final AtomicReference<BatchState> state;
-        private FlowExtCompletedOperation overall;
-
-        public FlowRuleBatchFuture(long batchId, List<Future<FlowExtCompletedOperation>> futures) {
-            this.futures = futures;
-            this.batchId = batchId;
-            state = new AtomicReference<FlowRuleExtManager.BatchState>();
-            state.set(BatchState.STARTED);
-        }
-
-        /**
-         * Attempts to cancel execution of this task.
-         *
-         * @param mayInterruptIfRunning {@code true} if the thread executing this
-         *                              task should be interrupted; otherwise, in-progress tasks are allowed
-         *                              to complete
-         * @return {@code false} if the task could not be cancelled,
-         * typically because it has already completed normally;
-         * {@code true} otherwise
-         */
-        @Override
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            if (state.get() == BatchState.FINISHED) {
-                return false;
-            }
-            if (log.isDebugEnabled()) {
-                log.debug("Cancelling FlowRuleBatchFuture",
-                          new RuntimeException("Just printing backtrace"));
-            }
-            if (!state.compareAndSet(BatchState.STARTED, BatchState.CANCELLED)) {
-                return false;
-            }
-            cleanUpBatch();
-            for (Future<FlowExtCompletedOperation> f : futures) {
-                f.cancel(mayInterruptIfRunning);
-            }
-            return true;
-        }
-
-        /**
-         * Judge whether the task cancelled completely.
-         *
-         * @return {@code true} if this task was cancelled before it completed
-         */
-        @Override
-        public boolean isCancelled() {
-            return state.get() == BatchState.CANCELLED;
-        }
-
-        /**
-         * Judge whether the task finished completely.
-         *
-         * @return {@code true} if this task completed
-         */
-        @Override
-        public boolean isDone() {
-            return state.get() == BatchState.FINISHED;
-        }
-
-        /**
-         * Get the result of apply flow extension rules.
-         * If the task isn't finished, the thread block here.
-         */
-        @Override
-        public FlowExtCompletedOperation get()
-                throws InterruptedException, ExecutionException {
-
-            if (isDone()) {
-                return overall;
-            }
-            boolean success = true;
-            Set<FlowRule> failed = Sets.newHashSet();
-            FlowExtCompletedOperation completed;
-            for (Future<FlowExtCompletedOperation> future : futures) {
-                completed = future.get();
-                success = validateBatchOperation(failed, completed);
-            }
-            return finalizeBatchOperation(success, failed);
-        }
-
-        /**
-         * Waits if necessary for at most the given time for the computation
-         * to complete, and then retrieves its result, if available. In here,
-         * the maximum of time out is sum of given time for every computation.
-         *
-         * @param timeout the maximum time to wait
-         * @param unit    the time unit of the timeout argument
-         * @return the computed result
-         * @throws CancellationException if the computation was cancelled
-         * @throws ExecutionException    if the computation threw an
-         *                               exception
-         * @throws InterruptedException  if the current thread was interrupted
-         *                               while waiting
-         * @throws TimeoutException      if the wait timed out
-         */
-        @Override
-        public FlowExtCompletedOperation get(long timeout, TimeUnit unit)
-                throws InterruptedException, ExecutionException,
-                TimeoutException {
-
-            if (isDone()) {
-                return overall;
-            }
-            boolean success = true;
-            Set<FlowRule> failed = Sets.newHashSet();
-            FlowExtCompletedOperation completed;
-            for (Future<FlowExtCompletedOperation> future : futures) {
-                completed = future.get(timeout, unit);
-                success = validateBatchOperation(failed, completed);
-            }
-            return finalizeBatchOperation(success, failed);
-        }
-
-        /**
-         * Confirm whether the batch operation success.
-         *
-         * @param failed    using to populate failed entries
-         * @param completed the result of apply flow extension entries
-         * @return {@code true} if all entries applies successful
-         */
-        private boolean validateBatchOperation(Set<FlowRule> failed,
-                                               FlowExtCompletedOperation completed) {
-
-            if (isCancelled()) {
-                throw new CancellationException();
-            }
-            if (!completed.isSuccess()) {
-                log.warn("FlowRuleBatch failed: {}", completed);
-                failed.addAll(completed.failedItems());
-                cleanUpBatch();
-                cancelAllSubBatches();
-                return false;
-            }
-            return true;
-        }
-
-        /**
-         * Once one subBatch failed, cancel the rest of them.
-         */
-        private void cancelAllSubBatches() {
-            for (Future<FlowExtCompletedOperation> f : futures) {
-                f.cancel(true);
-            }
-        }
-
-        /**
-         * Construct the result of batch operation.
-         *
-         * @param success the result of batch operation
-         * @param failed  the failed entries of batch operation
-         * @return FlowExtCompletedOperation of batch operation
-         */
-        private FlowExtCompletedOperation finalizeBatchOperation(boolean success,
-                                                                 Set<FlowRule> failed) {
-            synchronized (this) {
-                if (!state.compareAndSet(BatchState.STARTED,
-                                         BatchState.FINISHED)) {
-                    if (state.get() == BatchState.FINISHED) {
-                        return overall;
-                    }
-                    throw new CancellationException();
-                }
-                overall = new FlowExtCompletedOperation(batchId, success, failed);
-                return overall;
-            }
-        }
-
-        private void cleanUpBatch() {
-        }
-    }
-
-    /**
-     * South Bound API to south plug-in.
-     */
-    private class InternalFlowRuleExtRouterListener
-            implements FlowRuleExtRouterListener {
-        @Override
-        public void notify(FlowRuleBatchEvent event) {
-            // Request has been forwarded to MASTER Node
-            for (FlowRuleBatchEntry entry : event.subject().ops()) {
-                switch (entry.operator()) {
-                    case ADD:
-                        eventDispatcher
-                                .post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED,
-                                                        entry.target()));
-                        break;
-                    // FALLTHROUGH
-                    case REMOVE:
-                    case MODIFY:
-                    default:
-                        // TODO not implemented
-                        break;
-                }
-            }
-            // send it
-            FlowRuleProvider flowRuleProvider = getProvider(event.subject().ops()
-                                                                    .iterator().next().target().deviceId());
-            // TODO we may want to specify a deviceId
-            flowRuleProvider.executeBatch(event.subject().asBatchOperation(null));
-            // do not have transaction, assume it install success
-            // temporarily
-            FlowExtCompletedOperation result = new FlowExtCompletedOperation(
-                    event.subject().batchId(), true, Collections.emptySet());
-            futureService.submit(() -> {
-                router.batchOperationComplete(FlowRuleBatchEvent
-                                                      .completed(event.subject(), result));
-            });
-        }
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/flowext/impl/package-info.java b/core/net/src/main/java/org/onosproject/net/flowext/impl/package-info.java
deleted file mode 100644
index 8446bc3..0000000
--- a/core/net/src/main/java/org/onosproject/net/flowext/impl/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2015 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.
- */
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * <p>
- * This package is an extension for the current ONOS flow rule subsystem.
- * Its main purpose is to support external applications to push service data to network elements.
- * The service data could be any kind of service related data or commands required for corresponding service
- * setup and other operations as defined by application and its communicating device.
- * </p>
- */
-package org.onosproject.net.flowext.impl;
diff --git a/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/DefaultFlowRuleExtRouter.java b/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/DefaultFlowRuleExtRouter.java
deleted file mode 100644
index b7d69b2..0000000
--- a/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/DefaultFlowRuleExtRouter.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright 2015 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.store.flowext.impl;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.CompletedBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
-import org.onosproject.net.flowext.DefaultFlowRuleExt;
-import org.onosproject.net.flowext.DownStreamFlowEntry;
-import org.onosproject.net.flowext.FlowExtCompletedOperation;
-import org.onosproject.net.flowext.FlowRuleExtRouter;
-import org.onosproject.net.flowext.FlowRuleExtRouterListener;
-import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
-import org.onosproject.store.cluster.messaging.ClusterMessage;
-import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
-import org.onosproject.store.flow.ReplicaInfo;
-import org.onosproject.store.flow.ReplicaInfoEventListener;
-import org.onosproject.store.flow.ReplicaInfoService;
-import org.onosproject.store.serializers.KryoSerializer;
-import org.onosproject.store.serializers.StoreSerializer;
-import org.onosproject.store.serializers.impl.DistributedStoreSerializers;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.store.flowext.impl.FlowExtRouterMessageSubjects.APPLY_EXTEND_FLOWS;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * Implement a simple routing-like mechanism to directly send service data to its master and push to device.
- * This Router does not save any flow rule extension data in cache, it focus on routing mechanism.
- */
-@Component(immediate = true, enabled = false)
-@Service
-public class DefaultFlowRuleExtRouter
-        implements FlowRuleExtRouter {
-
-    private final Logger log = getLogger(getClass());
-
-    // TODO: Make configurable.
-    private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 4;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ReplicaInfoService replicaInfoManager;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterCommunicationService clusterCommunicator;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterService clusterService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
-
-    private int pendingFutureTimeoutMinutes = 5;
-
-    protected Set<FlowRuleExtRouterListener> routerListener = new HashSet<>();
-    private Cache<Long, SettableFuture<FlowExtCompletedOperation>> pendingExtendFutures = CacheBuilder
-            .newBuilder()
-            .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES)
-                    // .removalListener(new TimeoutFuture())
-            .build();
-
-    private final ExecutorService futureListeners = Executors
-            .newCachedThreadPool(groupedThreads("onos/flow", "store-peer-responders"));
-
-    private ExecutorService messageHandlingExecutor;
-
-    protected static final StoreSerializer SERIALIZER = new KryoSerializer() {
-        @Override
-        protected void setupKryoPool() {
-            serializerPool = KryoNamespace.newBuilder()
-                    .register(DistributedStoreSerializers.STORE_COMMON)
-                    .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
-                    .register(FlowExtCompletedOperation.class)
-                    .register(FlowRuleBatchRequest.class)
-                    .register(DownStreamFlowEntry.class)
-                    .register(DefaultFlowRuleExt.class)
-                    .build();
-        }
-    };
-
-    private ReplicaInfoEventListener replicaInfoEventListener;
-
-    @Activate
-    public void activate() {
-
-        messageHandlingExecutor = Executors.newFixedThreadPool(
-                MESSAGE_HANDLER_THREAD_POOL_SIZE,
-                groupedThreads("onos/flow", "message-handlers"));
-
-        clusterCommunicator.addSubscriber(APPLY_EXTEND_FLOWS,
-            new ClusterMessageHandler() {
-
-              @Override
-              public void handle(ClusterMessage message) {
-                  // decode the extended flow entry and store them in memory.
-                  FlowRuleBatchRequest operation = SERIALIZER.decode(message.payload());
-                  log.info("received batch request {}", operation);
-                  final ListenableFuture<FlowExtCompletedOperation> f = applyBatchInternal(operation);
-                  f.addListener(new Runnable() {
-                      @Override
-                      public void run() {
-                          FlowExtCompletedOperation result = Futures.getUnchecked(f);
-                          message.respond(SERIALIZER.encode(result));
-                      }
-                  }, futureListeners);
-              }
-            }, messageHandlingExecutor);
-
-        replicaInfoManager.addListener(replicaInfoEventListener);
-
-        log.info("Started");
-    }
-
-    @Deactivate
-    public void deactivate() {
-        clusterCommunicator.removeSubscriber(APPLY_EXTEND_FLOWS);
-        messageHandlingExecutor.shutdown();
-        replicaInfoManager.removeListener(replicaInfoEventListener);
-        log.info("Stopped");
-    }
-
-    /**
-     * apply the sub batch of flow extension rules.
-     *
-     * @param batchOperation batch of flow rules.
-     *                       A batch can contain flow rules for a single device only.
-     * @return Future response indicating success/failure of the batch operation
-     * all the way down to the device.
-     */
-    @Override
-    public Future<FlowExtCompletedOperation> applySubBatch(FlowRuleBatchRequest batchOperation) {
-        // TODO Auto-generated method stub
-        if (batchOperation.ops().isEmpty()) {
-            return Futures.immediateFuture(new FlowExtCompletedOperation(
-                    batchOperation.batchId(), true, Collections.emptySet()));
-        }
-        // get the deviceId all the collection belongs to
-        DeviceId deviceId = getBatchDeviceId(batchOperation.ops());
-
-        if (deviceId == null) {
-            log.error("This Batch exists more than two deviceId");
-            return null;
-        }
-        ReplicaInfo replicaInfo = replicaInfoManager
-                .getReplicaInfoFor(deviceId);
-
-        if (replicaInfo.master().get()
-                .equals(clusterService.getLocalNode().id())) {
-            return applyBatchInternal(batchOperation);
-        }
-
-        log.trace("Forwarding storeBatch to {}, which is the primary (master) for device {}",
-                  replicaInfo.master().orNull(), deviceId);
-
-        return clusterCommunicator.sendAndReceive(
-                batchOperation,
-                APPLY_EXTEND_FLOWS,
-                SERIALIZER::encode,
-                SERIALIZER::decode,
-                replicaInfo.master().get());
-    }
-
-    /**
-     * apply the batch in local node.
-     * It means this instance is master of the device the flow entry belongs to.
-     *
-     * @param batchOperation a collection of flow entry, all they should send down to one device
-     * @return Future response indicating success/failure of the batch operation
-     * all the way down to the device.
-     */
-    private ListenableFuture<FlowExtCompletedOperation> applyBatchInternal(FlowRuleBatchRequest batchOperation) {
-        SettableFuture<FlowExtCompletedOperation> r = SettableFuture.create();
-        pendingExtendFutures.put(batchOperation.batchId(), r);
-        // here should notify manager to complete
-        notify(batchOperation);
-        return r;
-    }
-
-    /**
-     * Get the deviceId of this batch.
-     * The whole Batch should belong to one deviceId.
-     *
-     * @param batchOperation a collection of flow entry, all they should send down to one device
-     * @return the deviceId the whole batch belongs to
-     */
-    private DeviceId getBatchDeviceId(Collection<FlowRuleBatchEntry> batchOperation) {
-        Iterator<FlowRuleBatchEntry> head = batchOperation.iterator();
-        FlowRuleBatchEntry headOp = head.next();
-        boolean sameId = true;
-        for (FlowRuleBatchEntry operation : batchOperation) {
-            if (operation.target().deviceId() != headOp.target().deviceId()) {
-                log.warn("this batch does not apply on one device Id ");
-                sameId = false;
-                break;
-            }
-        }
-        return sameId ? headOp.target().deviceId() : null;
-    }
-
-    /**
-     * Notify the listener of Router to do some reaction.
-     *
-     * @param request the requested operation to do
-     */
-    public void notify(FlowRuleBatchRequest request) {
-        for (FlowRuleExtRouterListener listener : routerListener) {
-            listener.notify(FlowRuleBatchEvent
-                                    // TODO fill in the deviceId
-                                    .requested(request, null));
-        }
-    }
-
-    /**
-     * Invoked on the completion of a storeBatch operation.
-     *
-     * @param event flow rule batch event
-     */
-    @Override
-    public void batchOperationComplete(FlowRuleBatchEvent event) {
-        // TODO Auto-generated method stub
-        final Long batchId = event.subject().batchId();
-        SettableFuture<FlowExtCompletedOperation> future = pendingExtendFutures
-                .getIfPresent(batchId);
-        if (future != null) {
-            FlowRuleBatchRequest request = event.subject();
-            CompletedBatchOperation result = event.result();
-            FlowExtCompletedOperation completed =
-                    new FlowExtCompletedOperation(request.batchId(), result.isSuccess(), result.failedItems());
-            future.set(completed);
-            pendingExtendFutures.invalidate(batchId);
-        }
-    }
-
-    /**
-     * Register the listener to monitor Router,
-     * The Router find master to send downStream.
-     *
-     * @param listener the listener to register
-     */
-    @Override
-    public void addListener(FlowRuleExtRouterListener listener) {
-        routerListener.add(listener);
-    }
-
-    /**
-     * Remove the listener of Router.
-     *
-     * @param listener the listener to remove
-     */
-    @Override
-    public void removeListener(FlowRuleExtRouterListener listener) {
-        routerListener.remove(listener);
-    }
-}
\ No newline at end of file
diff --git a/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/FlowExtRouterMessageSubjects.java b/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/FlowExtRouterMessageSubjects.java
deleted file mode 100644
index 05cb9d7..0000000
--- a/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/FlowExtRouterMessageSubjects.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2015 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.store.flowext.impl;
-
-import org.onosproject.store.cluster.messaging.MessageSubject;
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * MessageSubjects used by DefaultFlowRuleExtRouter peer-peer communication.
- */
-public final class FlowExtRouterMessageSubjects {
-    private FlowExtRouterMessageSubjects() {
-    }
-
-    /**
-     * The subject of routing extended flow to specified device.
-     */
-    public static final MessageSubject APPLY_EXTEND_FLOWS
-            = new MessageSubject("peer-forward-apply-batch-extension");
-}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/package-info.java b/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/package-info.java
deleted file mode 100644
index 23a28f7..0000000
--- a/core/store/dist/src/main/java/org/onosproject/store/flowext/impl/package-info.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2015 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.
- */
-
-/**
- * Experimental extension to the flow rule subsystem; still under development.
- * <p>
- * Implementation of the distributed flow extension rule router using p2p synchronization
- * protocol. The Router is the core component of routing flow rules to specified device.
- * This package is still experimental at this point in time.
- * </p>
- */
-package org.onosproject.store.flowext.impl;
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index bdd011d..7b17109 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -18,6 +18,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+
 import org.onlab.packet.ChassisId;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
@@ -70,6 +71,7 @@
 import org.onosproject.net.flow.FlowRuleBatchEvent;
 import org.onosproject.net.flow.FlowRuleBatchOperation;
 import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.FlowRuleExtPayLoad;
 import org.onosproject.net.flow.StoredFlowEntry;
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion;
@@ -322,7 +324,8 @@
                     ObstacleConstraint.class,
                     AnnotationConstraint.class,
                     BooleanConstraint.class,
-                    IntentOperation.class
+                    IntentOperation.class,
+                    FlowRuleExtPayLoad.class
                     )
             .register(new DefaultApplicationIdSerializer(), DefaultApplicationId.class)
             .register(new URISerializer(), URI.class)
diff --git a/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java b/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
new file mode 100644
index 0000000..8108afe
--- /dev/null
+++ b/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
@@ -0,0 +1,59 @@
+package org.onosproject.openflow.controller;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+import com.google.common.hash.PrimitiveSink;
+/**
+ * Used to support for the third party privacy flow rule.
+ * it implements OFMessage interface to use exist adapter API.
+ */
+public class ThirdPartyMessage implements OFMessage {
+
+    private final byte[] payLoad; //privacy flow rule
+
+    public ThirdPartyMessage(byte[] payLoad) {
+        this.payLoad = payLoad;
+    }
+
+    public byte[] payLoad() {
+        return payLoad;
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+     // Do nothing here for now.
+    }
+
+    @Override
+    public OFVersion getVersion() {
+     // Do nothing here for now.
+        return null;
+    }
+
+    @Override
+    public OFType getType() {
+     // Do nothing here for now.
+        return null;
+    }
+
+    @Override
+    public long getXid() {
+     // Do nothing here for now.
+        return 0;
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer channelBuffer) {
+     // Do nothing here for now.
+    }
+
+    @Override
+    public Builder createBuilder() {
+     // Do nothing here for now.
+        return null;
+    }
+
+}
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index add2752..d04af51 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014-2015 Open Networking Laboratory
+ * Copyright 2014 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.
@@ -15,13 +15,16 @@
  */
 package org.onosproject.provider.of.flow.impl;
 
+import static org.slf4j.LoggerFactory.getLogger;
 
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalCause;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -45,6 +48,7 @@
 import org.onosproject.openflow.controller.OpenFlowSwitch;
 import org.onosproject.openflow.controller.OpenFlowSwitchListener;
 import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.ThirdPartyMessage;
 import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
 import org.projectfloodlight.openflow.protocol.OFErrorMsg;
 import org.projectfloodlight.openflow.protocol.OFErrorType;
@@ -58,23 +62,20 @@
 import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
 import org.slf4j.Logger;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-import static org.slf4j.LoggerFactory.getLogger;
-
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 /**
- * Provider which uses an OpenFlow controller to detect network
- * end-station hosts.
+ * Provider which uses an OpenFlow controller to detect network end-station
+ * hosts.
  */
 @Component(immediate = true)
-public class OpenFlowRuleProvider extends AbstractProvider implements FlowRuleProvider {
+public class OpenFlowRuleProvider extends AbstractProvider
+        implements FlowRuleProvider {
 
     private final Logger log = getLogger(getClass());
 
@@ -84,7 +85,6 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenFlowController controller;
 
-
     private FlowRuleProviderService providerService;
 
     private final InternalFlowProvider listener = new InternalFlowProvider();
@@ -93,7 +93,6 @@
 
     private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
 
-
     /**
      * Creates an OpenFlow host provider.
      */
@@ -107,15 +106,19 @@
         controller.addListener(listener);
         controller.addEventListener(listener);
 
-        pendingBatches = CacheBuilder.newBuilder()
+        pendingBatches = CacheBuilder
+                .newBuilder()
                 .expireAfterWrite(10, TimeUnit.SECONDS)
                 .removalListener((RemovalNotification<Long, InternalCacheEntry> notification) -> {
-                    if (notification.getCause() == RemovalCause.EXPIRED) {
-                        providerService.batchOperationCompleted(notification.getKey(),
-                                                                notification.getValue().failedCompletion());
-                    }
-                }).build();
-
+                                     if (notification.getCause() == RemovalCause.EXPIRED) {
+                                         providerService
+                                                 .batchOperationCompleted(notification
+                                                                                  .getKey(),
+                                                                          notification
+                                                                                  .getValue()
+                                                                                  .failedCompletion());
+                                     }
+                                 }).build();
 
         for (OpenFlowSwitch sw : controller.getSwitches()) {
             FlowStatsCollector fsc = new FlowStatsCollector(sw, POLL_INTERVAL);
@@ -123,7 +126,6 @@
             collectors.put(new Dpid(sw.getId()), fsc);
         }
 
-
         log.info("Started");
     }
 
@@ -143,13 +145,17 @@
     }
 
     private void applyRule(FlowRule flowRule) {
-        OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
+        OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId()
+                .uri()));
+        if (flowRule.payLoad().payLoad().length > 0) {
+            OFMessage msg = new ThirdPartyMessage(flowRule.payLoad().payLoad());
+            sw.sendMsg(msg);
+            return;
+        }
         sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
-                    Optional.empty()).buildFlowAdd());
-
+                                          Optional.empty()).buildFlowAdd());
     }
 
-
     @Override
     public void removeFlowRule(FlowRule... flowRules) {
         for (FlowRule flowRule : flowRules) {
@@ -159,10 +165,15 @@
     }
 
     private void removeRule(FlowRule flowRule) {
-        OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
-
+        OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId()
+                .uri()));
+        if (flowRule.payLoad().payLoad().length > 0) {
+            OFMessage msg = new ThirdPartyMessage(flowRule.payLoad().payLoad());
+            sw.sendMsg(msg);
+            return;
+        }
         sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
-                    Optional.empty()).buildFlowDel());
+                                          Optional.empty()).buildFlowDel());
     }
 
     @Override
@@ -172,50 +183,54 @@
     }
 
     @Override
-
     public void executeBatch(FlowRuleBatchOperation batch) {
 
         pendingBatches.put(batch.id(), new InternalCacheEntry(batch));
 
-
-        OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(batch.deviceId().uri()));
+        OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(batch.deviceId()
+                .uri()));
         OFFlowMod mod;
-
         for (FlowRuleBatchEntry fbe : batch.getOperations()) {
-
-            FlowModBuilder builder =
-                    FlowModBuilder.builder(fbe.target(), sw.factory(),
-                                           Optional.of(batch.id()));
+            // flow is the third party privacy flow
+            if (fbe.target().payLoad().payLoad().length > 0) {
+                OFMessage msg = new ThirdPartyMessage(fbe.target().payLoad()
+                        .payLoad());
+                sw.sendMsg(msg);
+                continue;
+            }
+            FlowModBuilder builder = FlowModBuilder.builder(fbe.target(), sw
+                    .factory(), Optional.of(batch.id()));
             switch (fbe.operator()) {
-                case ADD:
-                    mod = builder.buildFlowAdd();
-                    break;
-                case REMOVE:
-                    mod = builder.buildFlowDel();
-                    break;
-                case MODIFY:
-                    mod = builder.buildFlowMod();
-                    break;
-                default:
-                    log.error("Unsupported batch operation {}; skipping flowmod {}",
-                              fbe.operator(), fbe);
-                    continue;
-                }
+            case ADD:
+                mod = builder.buildFlowAdd();
+                break;
+            case REMOVE:
+                mod = builder.buildFlowDel();
+                break;
+            case MODIFY:
+                mod = builder.buildFlowMod();
+                break;
+            default:
+                log.error("Unsupported batch operation {}; skipping flowmod {}",
+                          fbe.operator(), fbe);
+                continue;
+            }
             sw.sendMsg(mod);
         }
-        OFBarrierRequest.Builder builder = sw.factory()
-                .buildBarrierRequest()
+        OFBarrierRequest.Builder builder = sw.factory().buildBarrierRequest()
                 .setXid(batch.id());
         sw.sendMsg(builder.build());
     }
 
-
     private class InternalFlowProvider
             implements OpenFlowSwitchListener, OpenFlowEventListener {
 
         @Override
         public void switchAdded(Dpid dpid) {
-            FlowStatsCollector fsc = new FlowStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
+            FlowStatsCollector fsc = new FlowStatsCollector(
+                                                            controller
+                                                                    .getSwitch(dpid),
+                                                            POLL_INTERVAL);
             fsc.start();
             collectors.put(dpid, fsc);
         }
@@ -234,64 +249,71 @@
 
         @Override
         public void portChanged(Dpid dpid, OFPortStatus status) {
-            //TODO: Decide whether to evict flows internal store.
+            // TODO: Decide whether to evict flows internal store.
         }
 
         @Override
         public void handleMessage(Dpid dpid, OFMessage msg) {
             OpenFlowSwitch sw = controller.getSwitch(dpid);
             switch (msg.getType()) {
-                case FLOW_REMOVED:
-                    OFFlowRemoved removed = (OFFlowRemoved) msg;
+            case FLOW_REMOVED:
+                OFFlowRemoved removed = (OFFlowRemoved) msg;
 
-                    FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
-                    providerService.flowRemoved(fr);
-                    break;
-                case STATS_REPLY:
-                    if (((OFStatsReply) msg).getStatsType() == OFStatsType.FLOW) {
-                        pushFlowMetrics(dpid, (OFFlowStatsReply) msg);
+                FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
+                providerService.flowRemoved(fr);
+                break;
+            case STATS_REPLY:
+                if (((OFStatsReply) msg).getStatsType() == OFStatsType.FLOW) {
+                    pushFlowMetrics(dpid, (OFFlowStatsReply) msg);
+                }
+                break;
+            case BARRIER_REPLY:
+                try {
+                    InternalCacheEntry entry = pendingBatches.getIfPresent(msg
+                            .getXid());
+                    if (entry != null) {
+                        providerService
+                                .batchOperationCompleted(msg.getXid(),
+                                                         entry.completed());
+                    } else {
+                        log.warn("Received unknown Barrier Reply: {}",
+                                 msg.getXid());
                     }
-                    break;
-                case BARRIER_REPLY:
-                    try {
-                        InternalCacheEntry entry = pendingBatches.getIfPresent(msg.getXid());
+                } finally {
+                    pendingBatches.invalidate(msg.getXid());
+                }
+                break;
+            case ERROR:
+                log.warn("received Error message {} from {}", msg, dpid);
+
+                OFErrorMsg error = (OFErrorMsg) msg;
+                if (error.getErrType() == OFErrorType.FLOW_MOD_FAILED) {
+                    OFFlowModFailedErrorMsg fmFailed = (OFFlowModFailedErrorMsg) error;
+                    if (fmFailed.getData().getParsedMessage().isPresent()) {
+                        OFMessage m = fmFailed.getData().getParsedMessage()
+                                .get();
+                        OFFlowMod fm = (OFFlowMod) m;
+                        InternalCacheEntry entry = pendingBatches
+                                .getIfPresent(msg.getXid());
                         if (entry != null) {
-                            providerService.batchOperationCompleted(msg.getXid(), entry.completed());
+                            entry.appendFailure(new FlowEntryBuilder(dpid, fm)
+                                    .build());
                         } else {
-                            log.warn("Received unknown Barrier Reply: {}", msg.getXid());
-                        }
-                    } finally {
-                        pendingBatches.invalidate(msg.getXid());
-                    }
-                    break;
-                case ERROR:
-                    log.warn("received Error message {} from {}", msg, dpid);
-
-                    OFErrorMsg error = (OFErrorMsg) msg;
-                    if (error.getErrType() == OFErrorType.FLOW_MOD_FAILED) {
-                        OFFlowModFailedErrorMsg fmFailed = (OFFlowModFailedErrorMsg) error;
-                        if (fmFailed.getData().getParsedMessage().isPresent()) {
-                            OFMessage m = fmFailed.getData().getParsedMessage().get();
-                            OFFlowMod fm = (OFFlowMod) m;
-                            InternalCacheEntry entry = pendingBatches.getIfPresent(msg.getXid());
-                            if (entry != null) {
-                                entry.appendFailure(new FlowEntryBuilder(dpid, fm)
-                                                                         .build());
-                            } else {
-                                log.error("No matching batch for this error: {}", error);
-                            }
-                        } else {
-                            //FIXME: Potentially add flowtracking to avoid this message.
-                            log.error("Flow installation failed but switch didn't" +
-                                              " tell us which one.");
+                            log.error("No matching batch for this error: {}",
+                                      error);
                         }
                     } else {
-                        log.warn("Received error {}", error);
+                        // FIXME: Potentially add flowtracking to avoid this
+                        // message.
+                        log.error("Flow installation failed but switch didn't"
+                                + " tell us which one.");
                     }
+                } else {
+                    log.warn("Received error {}", error);
+                }
 
-
-                default:
-                    log.debug("Unhandled message type: {}", msg.getType());
+            default:
+                log.debug("Unhandled message type: {}", msg.getType());
             }
 
         }
@@ -318,11 +340,11 @@
     }
 
     /**
-     * The internal cache entry holding the original request as well
-     * as accumulating the any failures along the way.
+     * The internal cache entry holding the original request as well as
+     * accumulating the any failures along the way.
      *
-     * If this entry is evicted from the cache then the entire operation
-     * is considered failed. Otherwise, only the failures reported by the device
+     * If this entry is evicted from the cache then the entire operation is
+     * considered failed. Otherwise, only the failures reported by the device
      * will be propagated up.
      */
     private class InternalCacheEntry {
@@ -336,6 +358,7 @@
 
         /**
          * Appends a failed rule to the set of failed items.
+         *
          * @param rule the failed rule
          */
         public void appendFailure(FlowRule rule) {
@@ -344,21 +367,29 @@
 
         /**
          * Fails the entire batch and returns the failed operation.
+         *
          * @return the failed operation
          */
         public CompletedBatchOperation failedCompletion() {
             Set<FlowRule> fails = operation.getOperations().stream()
                     .map(op -> op.target()).collect(Collectors.toSet());
-            return new CompletedBatchOperation(false, Collections.unmodifiableSet(fails), operation.deviceId());
+            return new CompletedBatchOperation(false,
+                                               Collections
+                                                       .unmodifiableSet(fails),
+                                               operation.deviceId());
         }
 
         /**
          * Returns the completed operation and whether the batch suceeded.
+         *
          * @return the completed operation
          */
         public CompletedBatchOperation completed() {
-            return new CompletedBatchOperation(failures.isEmpty(),
-                                               Collections.unmodifiableSet(failures), operation.deviceId());
+            return new CompletedBatchOperation(
+                                               failures.isEmpty(),
+                                               Collections
+                                                       .unmodifiableSet(failures),
+                                               operation.deviceId());
         }
 
     }
diff --git a/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java
index a460385..0f0dae8 100644
--- a/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/FlowsResourceTest.java
@@ -40,12 +40,14 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.FlowEntry;
 import org.onosproject.net.flow.FlowId;
+import org.onosproject.net.flow.FlowRuleExtPayLoad;
 import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.Criterion;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
+
 import com.eclipsesource.json.JsonArray;
 import com.eclipsesource.json.JsonObject;
 import com.google.common.collect.ImmutableSet;
@@ -190,6 +192,11 @@
         public int tableId() {
             return 0;
         }
+
+        @Override
+        public FlowRuleExtPayLoad payLoad() {
+            return null;
+        }
     }
 
     /**