ONOS-2724
Fix bug of apply flowrule and remove flowrule

Change-Id: Ia7dec83206c3f5e24f912f111bd87dab6eab4610
diff --git a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
index 382eeb6..01c9882 100644
--- a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
@@ -33,6 +33,8 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.util.KryoNamespace;
@@ -49,12 +51,16 @@
 import org.onosproject.net.behaviour.BridgeName;
 import org.onosproject.net.behaviour.DefaultTunnelDescription;
 import org.onosproject.net.behaviour.IpTunnelEndPoint;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.behaviour.PipelinerContext;
 import org.onosproject.net.behaviour.TunnelConfig;
 import org.onosproject.net.behaviour.TunnelDescription;
 import org.onosproject.net.behaviour.TunnelEndPoint;
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.Driver;
 import org.onosproject.net.driver.DriverHandler;
 import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -66,6 +72,7 @@
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flowobjective.DefaultForwardingObjective;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.FlowObjectiveStore;
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
 import org.onosproject.net.flowobjective.Objective;
@@ -115,6 +122,9 @@
     protected DriverService driverService;
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected FlowObjectiveService flowObjectiveService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowObjectiveStore flowObjectiveStore;
+    protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
     private EventuallyConsistentMap<HostId, SegmentationId> binding;
     private ApplicationId appId;
     private HostListener hostListener = new InnerHostListener();
@@ -128,6 +138,7 @@
     private static final int DEFAULT_PORT_PRIORITY = 0x0000;
     private static final int PORT_PRIORITY = 0xffff;
     private static final String SWITCH_CHANNEL_ID = "channelId";
+    private static final String DRIVER_NAME = "onosfw";
 
     @Activate
     public void activate() {
@@ -163,8 +174,7 @@
         IpAddress ip = IpAddress.valueOf(ipAddress);
         Sets.newHashSet(devices).stream()
                 .filter(d -> Device.Type.CONTROLLER == d.type())
-                .filter(d -> !device.id().equals(d.id()))
-                .forEach(d -> {
+                .filter(d -> !device.id().equals(d.id())).forEach(d -> {
                         String ipAddress1 = d.annotations()
                                 .value(CONTROLLER_IP_KEY);
                         IpAddress ip1 = IpAddress.valueOf(ipAddress1);
@@ -172,6 +182,7 @@
                         DriverHandler handler1 = driverService
                                 .createHandler(d.id());
                         applyTunnelConfig(ip1, ip, handler1);
+
                 });
     }
 
@@ -221,30 +232,6 @@
     public void onOvsDetected(Device device) {
         programMacDefaultRules(device.id(), appId, Objective.Operation.ADD);
         programPortDefaultRules(device.id(), appId, Objective.Operation.ADD);
-        Set<Host> hosts = hostService.getConnectedHosts(device.id());
-        hosts.forEach(h -> {
-            String ifaceId = h.annotations().value(IFACEID);
-            String currentControllerIp = getControllerIpOfSwitch(device.id());
-            VirtualPortId portId = VirtualPortId.portId(ifaceId);
-            VirtualPort port = virtualPortService.getPort(portId);
-            TenantNetwork network = tenantNetworkService
-                    .getNetwork(port.networkId());
-            String vxlanName = "vxlan-" + currentControllerIp;
-
-            DriverHandler handler = driverService.createHandler(device.id());
-            BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
-            Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
-                    .getBridges();
-            Iterator<BridgeDescription> it = bridgeDescriptions.iterator();
-            if (it.hasNext()) {
-                BridgeDescription sw = it.next();
-                Set<PortNumber> ports = bridgeConfig.getPortNumbers();
-                ports.stream().filter(p -> p.name().equalsIgnoreCase(vxlanName))
-                        .forEach(p -> programTunnelOut(sw.deviceId(), network.segmentationId(), p,
-                                h.mac(), appId, Objective.Operation.ADD));
-            }
-
-        });
     }
 
     @Override
@@ -267,27 +254,23 @@
         binding.put(host.id(), network.segmentationId());
         List<Port> allPorts = deviceService.getPorts(deviceId);
         PortNumber inPort = host.location().port();
-        Set<Port> localPorts = new HashSet<>();
-        Set<Port> tunnelPorts = new HashSet<>();
-        List<Port> outports = new ArrayList<>();
+        List<PortNumber> localVmPorts = getLocalPorts(deviceId, ifaceId);
+        List<PortNumber> localTunnelPorts = new ArrayList<>();
         Sets.newHashSet(allPorts.iterator()).stream()
         .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
-            if (!p.annotations().value("portName").startsWith(PORT_HEAD)) {
-                localPorts.add(p);
-            } else {
-                tunnelPorts.add(p);
+            if (p.annotations().value("portName").startsWith(PORT_HEAD)) {
+                localTunnelPorts.add(p.number());
             }
-            outports.add(p);
         });
 
-        programLocalBcastRules(deviceId, network.segmentationId(), inPort,
-                               outports, appId, Objective.Operation.ADD);
+        localVmPorts.forEach(lp -> programLocalBcastRules(deviceId, network.segmentationId(), lp, localVmPorts,
+                                                          localTunnelPorts, appId, Objective.Operation.ADD));
         programLocalOut(deviceId, network.segmentationId(), inPort, host.mac(),
                         appId, Objective.Operation.ADD);
-        tunnelPorts
+        localTunnelPorts
                 .forEach(tp -> programTunnelFloodOut(deviceId,
                                                      network.segmentationId(),
-                                                     tp.number(), localPorts,
+                                                     tp, localVmPorts,
                                                      appId,
                                                      Objective.Operation.ADD));
         Sets.newHashSet(devices).stream()
@@ -306,52 +289,54 @@
                         ports.stream()
                                 .filter(p -> p.name()
                                         .equalsIgnoreCase(tunnelName))
-                                .forEach(p -> programTunnelOut(sw.deviceId(),
-                                        network.segmentationId(), p,
-                                        host.mac(), appId,
-                                        Objective.Operation.ADD));
+                                .forEach(p -> {
+                            programTunnelOut(sw.deviceId(),
+                                             network.segmentationId(), p,
+                                             host.mac(), appId,
+                                             Objective.Operation.ADD);
+                        });
                     }
                 });
         programLocalIn(deviceId, network.segmentationId(), inPort, host.mac(),
                        appId, Objective.Operation.ADD);
-        tunnelPorts
+        localTunnelPorts
                 .forEach(tp -> programTunnelIn(deviceId,
                                                network.segmentationId(),
-                                               tp.number(), inPort, host.mac(),
+                                               tp, inPort, host.mac(),
                                                appId, Objective.Operation.ADD));
 
     }
 
     @Override
     public void onHostVanished(Host host) {
+        String ifaceId = host.annotations().value(IFACEID);
         SegmentationId segId = binding.remove(host.id());
         DeviceId deviceId = host.location().deviceId();
         String currentControllerIp = getControllerIpOfSwitch(deviceId);
         Iterable<Device> devices = deviceService.getAvailableDevices();
+
+        String tunnelName = "vxlan-" + currentControllerIp;
         List<Port> allPorts = deviceService.getPorts(deviceId);
         PortNumber inPort = host.location().port();
-        String vxlanName = "vxlan-" + currentControllerIp;
-        Set<Port> localPorts = new HashSet<>();
-        Set<Port> tunnelPorts = new HashSet<>();
-        List<Port> outports = new ArrayList<>();
+
+        List<PortNumber> localTunnelPorts = new ArrayList<>();
         Sets.newHashSet(allPorts.iterator()).stream()
         .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
-            if (!p.annotations().value("portName").startsWith(PORT_HEAD)) {
-                localPorts.add(p);
-            } else {
-                tunnelPorts.add(p);
+            if (p.annotations().value("portName").startsWith(PORT_HEAD)) {
+                localTunnelPorts.add(p.number());
             }
-            outports.add(p);
         });
 
-        programLocalBcastRules(deviceId, segId, inPort,
-                               outports, appId, Objective.Operation.REMOVE);
+        List<PortNumber> localVmPorts = getLocalPorts(deviceId, ifaceId);
+        localVmPorts.add(inPort);
+        localVmPorts.forEach(lp -> programLocalBcastRules(deviceId, segId, lp, localVmPorts,
+                                                          localTunnelPorts, appId, Objective.Operation.REMOVE));
         programLocalOut(deviceId, segId, inPort, host.mac(),
                         appId, Objective.Operation.REMOVE);
-        tunnelPorts
+        localTunnelPorts
                 .forEach(tp -> programTunnelFloodOut(deviceId,
                                                      segId,
-                                                     tp.number(), localPorts,
+                                                     tp, localVmPorts,
                                                      appId,
                                                      Objective.Operation.REMOVE));
         Sets.newHashSet(devices).stream()
@@ -369,19 +354,21 @@
                         Set<PortNumber> ports = bridgeConfig.getPortNumbers();
                         ports.stream()
                                 .filter(p -> p.name()
-                                        .equalsIgnoreCase(vxlanName))
-                                .forEach(p -> programTunnelOut(sw.deviceId(),
-                                        segId, p,
-                                        host.mac(), appId,
-                                        Objective.Operation.REMOVE));
+                                        .equalsIgnoreCase(tunnelName))
+                                .forEach(p -> {
+                            programTunnelOut(sw.deviceId(),
+                                             segId, p,
+                                             host.mac(), appId,
+                                             Objective.Operation.REMOVE);
+                        });
                     }
                 });
         programLocalIn(deviceId, segId, inPort, host.mac(),
                        appId, Objective.Operation.REMOVE);
-        tunnelPorts
+        localTunnelPorts
                 .forEach(tp -> programTunnelIn(deviceId,
                                                segId,
-                                               tp.number(), inPort, host.mac(),
+                                               tp, inPort, host.mac(),
                                                appId, Objective.Operation.REMOVE));
     }
 
@@ -448,19 +435,18 @@
                                  ApplicationId appid,
                                  Objective.Operation type) {
         TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchTunnelId(Long.parseLong(segmentationId.toString()))
                 .matchEthDst(sourceMac).build();
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .add(Instructions
-                        .modTunnelId(Long.parseLong(segmentationId.toString())))
                 .setOutput(outPort).build();
         ForwardingObjective.Builder objective = DefaultForwardingObjective
                 .builder().withTreatment(treatment).withSelector(selector)
                 .fromApp(appId).withFlag(Flag.SPECIFIC)
                 .withPriority(MAC_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(dpid, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(dpid, objective.remove());
         }
 
     }
@@ -482,19 +468,19 @@
                 .fromApp(appId).withFlag(Flag.SPECIFIC)
                 .withPriority(MAC_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(dpid, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(dpid, objective.remove());
         }
 
     }
 
     // Used to forward multicast flows to remote VMs of the same tenant via
     // VXLAN tunnel.
-    private void programTunnelFloodOut(DeviceId dpid,
+    private void programTunnelFloodOut(DeviceId deviceId,
                                        SegmentationId segmentationId,
                                        PortNumber ofPortOut,
-                                       Iterable<Port> localports,
+                                       List<PortNumber> localVmPorts,
                                        ApplicationId appid,
                                        Objective.Operation type) {
         TrafficSelector selector = DefaultTrafficSelector.builder()
@@ -504,8 +490,9 @@
                              .toString()))).matchEthDst(MacAddress.BROADCAST)
                 .build();
         TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-        for (Port outport : localports) {
-            treatment.setOutput(outport.number());
+
+        for (PortNumber outPort : localVmPorts) {
+                treatment.setOutput(outPort);
         }
 
         ForwardingObjective.Builder objective = DefaultForwardingObjective
@@ -513,9 +500,9 @@
                 .withSelector(selector).fromApp(appId).makePermanent()
                 .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(deviceId, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(deviceId, objective.remove());
         }
     }
 
@@ -530,16 +517,18 @@
                 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
                 .withPriority(DEFAULT_MAC_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(dpid, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(dpid, objective.remove());
         }
     }
 
     // Used to forward the flows to the local VMs with the same tenant.
-    private void programLocalBcastRules(DeviceId dpid,
+    private void programLocalBcastRules(DeviceId deviceId,
                                         SegmentationId segmentationId,
-                                        PortNumber inPort, List<Port> allports,
+                                        PortNumber inPort,
+                                        List<PortNumber> localVmPorts,
+                                        List<PortNumber> localTunnelPorts,
                                         ApplicationId appid,
                                         Objective.Operation type) {
         TrafficSelector selector = DefaultTrafficSelector.builder()
@@ -548,20 +537,22 @@
                         .parseLong(segmentationId.toString())))
                 .build();
         TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
-
-        for (Port outport : allports) {
-            if (inPort != outport.number()) {
-                treatment.setOutput(outport.number());
+        for (PortNumber outPort : localVmPorts) {
+            if (inPort != outPort) {
+                treatment.setOutput(outPort);
             }
         }
+        for (PortNumber outport : localTunnelPorts) {
+                treatment.setOutput(outport);
+        }
         ForwardingObjective.Builder objective = DefaultForwardingObjective
                 .builder().withTreatment(treatment.build())
                 .withSelector(selector).fromApp(appId).makePermanent()
                 .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(deviceId, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(deviceId, objective.remove());
         }
     }
 
@@ -579,9 +570,9 @@
                 .withSelector(selector).fromApp(appId).makePermanent()
                 .withFlag(Flag.SPECIFIC).withPriority(PORT_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(dpid, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(dpid, objective.remove());
         }
     }
 
@@ -601,9 +592,9 @@
                 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
                 .withPriority(PORT_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(dpid, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(dpid, objective.remove());
         }
     }
 
@@ -617,9 +608,9 @@
                 .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
                 .withPriority(DEFAULT_PORT_PRIORITY);
         if (type.equals(Objective.Operation.ADD)) {
-            flowObjectiveService.forward(dpid, objective.add());
+            flowServiceForward(dpid, objective.add());
         } else {
-            flowObjectiveService.forward(dpid, objective.remove());
+            flowServiceForward(dpid, objective.remove());
         }
     }
 
@@ -630,4 +621,61 @@
         return url.substring(0, url.lastIndexOf(":"));
     }
 
+    private Iterable<String> getIfaceIds(String ifaceId) {
+        VirtualPortId portId = VirtualPortId.portId(ifaceId);
+        VirtualPort port = virtualPortService.getPort(portId);
+        TenantNetwork network = tenantNetworkService
+                .getNetwork(port.networkId());
+        Collection<String> ifaceIds = new HashSet<String>();
+        Collection<VirtualPort> ports = virtualPortService
+                .getPorts(network.id());
+        Sets.newHashSet(ports).stream()
+                .forEach(p -> ifaceIds.add(p.portId().portId()));
+        return ifaceIds;
+    }
+
+    private List<PortNumber> getLocalPorts(DeviceId deviceId, String ifaceId) {
+        DriverHandler handler = driverService
+                .createHandler(getController(deviceId));
+        BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+        Iterable<String> ifaceIds = getIfaceIds(ifaceId);
+        return bridgeConfig.getLocalPorts(ifaceIds);
+    }
+
+    private DeviceId getController(DeviceId deviceId) {
+        Iterable<Device> devices = deviceService.getAvailableDevices();
+        for (Device device : devices) {
+            if (device.type() == Device.Type.CONTROLLER && device.id()
+                    .toString().contains(getControllerIpOfSwitch(deviceId))) {
+                return device.id();
+            }
+        }
+        log.info("Can not find controller for device : {}", deviceId);
+        return null;
+    }
+
+    //Used to apply flowRule
+    private void flowServiceForward(DeviceId deviceId, ForwardingObjective forwardingObjective) {
+        Driver driver = driverService.getDriver(DRIVER_NAME);
+        Pipeliner pipeLiner = driver.createBehaviour(new DefaultDriverData(driver, deviceId), Pipeliner.class);
+        if (pipeLiner != null) {
+            final PipelinerContext context = new InnerPipelineContext();
+            pipeLiner.init(deviceId, context);
+            pipeLiner.forward(forwardingObjective);
+        }
+    }
+
+    // Processing context for initializing pipeline driver behaviours.
+    private class InnerPipelineContext implements PipelinerContext {
+        @Override
+        public ServiceDirectory directory() {
+            return serviceDirectory;
+        }
+
+        @Override
+        public FlowObjectiveStore store() {
+            return flowObjectiveStore;
+        }
+    }
+
 }
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java b/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
index 96397ea..7f157e9 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
@@ -1,78 +1,87 @@
-/*

- * 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.behaviour;

-

-import java.util.Collection;

-import java.util.Set;

-

-import org.onosproject.net.PortNumber;

-import org.onosproject.net.device.PortDescription;

-import org.onosproject.net.driver.HandlerBehaviour;

-

-/**

- * Behaviour for handling various drivers for bridge configurations.

- */

-public interface BridgeConfig extends HandlerBehaviour {

-

-    /**

-     * Add a bridge.

-     *

-     * @param bridgeName bridge name

-     */

-    void addBridge(BridgeName bridgeName);

-

-    /**

-     * Remove a bridge.

-     *

-     * @param bridgeName bridge name

-     */

-    void deleteBridge(BridgeName bridgeName);

-

-    /**

-     * Remove a bridge.

-     *

-     * @return bridge collection

-     */

-    Collection<BridgeDescription> getBridges();

-

-    /**

-     * Add a logical/virtual port.

-     *

-     * @param port port number

-     */

-    void addPort(PortDescription port);

-

-    /**

-     * Delete a logical/virtual port.

-     *

-     * @param port port number

-     */

-    void deletePort(PortDescription port);

-

-    /**

-     * Delete a logical/virtual port.

-     *

-     * @return collection of port

-     */

-    Collection<PortDescription> getPorts();

-

-    /**

-     * Get a collection of port.

-     *

-     * @return portNumbers set of PortNumber

-     */

-    Set<PortNumber> getPortNumbers();

-}

+/*
+ * 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.behaviour;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+/**
+ * Behaviour for handling various drivers for bridge configurations.
+ */
+public interface BridgeConfig extends HandlerBehaviour {
+
+    /**
+     * Add a bridge.
+     *
+     * @param bridgeName bridge name
+     */
+    void addBridge(BridgeName bridgeName);
+
+    /**
+     * Remove a bridge.
+     *
+     * @param bridgeName bridge name
+     */
+    void deleteBridge(BridgeName bridgeName);
+
+    /**
+     * Remove a bridge.
+     *
+     * @return bridge collection
+     */
+    Collection<BridgeDescription> getBridges();
+
+    /**
+     * Add a logical/virtual port.
+     *
+     * @param port port number
+     */
+    void addPort(PortDescription port);
+
+    /**
+     * Delete a logical/virtual port.
+     *
+     * @param port port number
+     */
+    void deletePort(PortDescription port);
+
+    /**
+     * Delete a logical/virtual port.
+     *
+     * @return collection of port
+     */
+    Collection<PortDescription> getPorts();
+
+    /**
+     * Get a collection of port.
+     *
+     * @return portNumbers set of PortNumber
+     */
+    Set<PortNumber> getPortNumbers();
+
+    /**
+     * Get logical/virtual ports by ifaceIds.
+     *
+     * @param ifaceIds the ifaceid that needed
+     * @return list of PortNumber
+     */
+    List<PortNumber> getLocalPorts(Iterable<String> ifaceIds);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
index 5c6a08b..b7a9f2b 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
@@ -153,8 +153,8 @@
     // Creates an instance of behaviour primed with the specified driver data.
     private <T extends Behaviour> T createBehaviour(DriverData data, DriverHandler handler,
                                                     Class<T> behaviourClass) {
-        checkArgument(handler != null || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
-                      "{} is applicable only to handler context", behaviourClass.getName());
+        //checkArgument(handler != null || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
+        //              "{} is applicable only to handler context", behaviourClass.getName());
 
         // Locate the implementation of the requested behaviour.
         Class<? extends Behaviour> implementation = behaviours.get(behaviourClass);
diff --git a/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java b/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
index 401a64f..524163a 100644
--- a/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
+++ b/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
@@ -15,7 +15,9 @@
  */
 package org.onosproject.driver.ovsdb;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -146,4 +148,18 @@
                 )
                 .collect(Collectors.toSet());
     }
+
+    @Override
+    public List<PortNumber> getLocalPorts(Iterable<String> ifaceIds) {
+        List<PortNumber> ports = new ArrayList<>();
+        DriverHandler handler = handler();
+        OvsdbClientService clientService = getOvsdbClientService(handler);
+        Set<OvsdbPort> ovsdbSet = clientService.getLocalPorts(ifaceIds);
+        ovsdbSet.forEach(o -> {
+            PortNumber port = PortNumber.portNumber(o.portNumber().value(),
+                                                    o.portName().value());
+            ports.add(port);
+        });
+        return ports;
+    }
 }
diff --git a/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
index fd728e9..270e76a 100644
--- a/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
+++ b/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
@@ -26,7 +26,6 @@
 import org.onosproject.net.behaviour.Pipeliner;
 import org.onosproject.net.behaviour.PipelinerContext;
 import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.flow.DefaultFlowRule;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.FlowRule;
@@ -48,9 +47,10 @@
 /**
  * Driver for standard OpenVSwitch.
  */
-public class OpenVSwitchPipeline extends AbstractHandlerBehaviour
+public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
         implements Pipeliner {
 
+    private static final String VTN_APP_ID = "org.onosproject.app.vtn";
     private final Logger log = getLogger(getClass());
     private CoreService coreService;
     private ServiceDirectory serviceDirectory;
@@ -58,14 +58,13 @@
     protected DeviceId deviceId;
     protected FlowRuleService flowRuleService;
     protected DeviceService deviceService;
-    private static final int MAC_TABLE_PRIORITY = 0xffff;
-    private static final int PORT_TABLE_PRIORITY = 0xffff;
     private static final int TIME_OUT = 0;
     private static final int MAC_TABLE = 40;
     private static final int PORT_TABLE = 0;
 
     @Override
     public void init(DeviceId deviceId, PipelinerContext context) {
+        super.init(deviceId, context);
         this.serviceDirectory = context.directory();
         this.deviceId = deviceId;
 
@@ -79,11 +78,15 @@
 
     @Override
     public void filter(FilteringObjective filteringObjective) {
-        // TODO Auto-generated method stub
+        super.filter(filteringObjective);
     }
 
     @Override
     public void forward(ForwardingObjective fwd) {
+        if (!VTN_APP_ID.equals(fwd.appId().name())) {
+            super.forward(fwd);
+            return;
+        }
         Collection<FlowRule> rules;
         FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations
                 .builder();
@@ -119,8 +122,7 @@
 
     @Override
     public void next(NextObjective nextObjective) {
-        // TODO Auto-generated method stub
-
+        super.next(nextObjective);
     }
 
     private Collection<FlowRule> processForward(ForwardingObjective fwd) {
@@ -148,18 +150,16 @@
         FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
                 .fromApp(fwd.appId()).withPriority(fwd.priority())
                 .forDevice(deviceId).withSelector(selector)
-                .makeTemporary(TIME_OUT);
-
+                .withTreatment(tb).makeTemporary(TIME_OUT);
+        ruleBuilder.withPriority(fwd.priority());
         if (fwd.permanent()) {
             ruleBuilder.makePermanent();
         }
         if (selector.getCriterion(Type.ETH_DST) != null
                 || tb.allInstructions().contains(Instructions.createDrop())) {
-            ruleBuilder.withPriority(MAC_TABLE_PRIORITY);
             ruleBuilder.withTreatment(tb);
             ruleBuilder.forTable(MAC_TABLE);
         } else {
-            ruleBuilder.withPriority(PORT_TABLE_PRIORITY);
             TrafficTreatment.Builder newTraffic = DefaultTrafficTreatment.builder();
             tb.allInstructions().forEach(t -> newTraffic.add(t));
             newTraffic.transition(MAC_TABLE);
diff --git a/drivers/src/main/resources/onos-drivers.xml b/drivers/src/main/resources/onos-drivers.xml
index b256864..ac307c2 100644
--- a/drivers/src/main/resources/onos-drivers.xml
+++ b/drivers/src/main/resources/onos-drivers.xml
@@ -115,5 +115,10 @@
         <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
                    impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
     </driver>
+    <driver name="onosfw" extends="default"
+            manufacturer="" hwVersion="" swVersion="">
+        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
+                   impl="org.onosproject.driver.pipeline.OpenVSwitchPipeline"/>
+    </driver>
 </drivers>
 
diff --git a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index 8bccd5c..ab88a24 100644
--- a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -212,7 +212,7 @@
     void removeRow(String dbName, String tableName, String uuid);
 
     /**
-     * Update the local ovsdb store.
+     * Updates the local ovsdb store.
      *
      * @param dbName database name
      * @param tableName table name
@@ -221,4 +221,11 @@
      */
     void updateOvsdbStore(String dbName, String tableName, String uuid, Row row);
 
+    /**
+     * Gets ovsdb local ports.
+     *
+     * @param ifaceids the ifaceid that needed
+     * @return ovsdb ports
+     */
+    Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids);
 }
diff --git a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index a271f93..0c64cc0 100644
--- a/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -46,6 +46,7 @@
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
 import org.onosproject.ovsdb.rfc.notation.Condition;
 import org.onosproject.ovsdb.rfc.notation.Mutation;
+import org.onosproject.ovsdb.rfc.notation.OvsdbMap;
 import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
 import org.onosproject.ovsdb.rfc.notation.Row;
 import org.onosproject.ovsdb.rfc.notation.UUID;
@@ -74,6 +75,7 @@
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
@@ -1125,4 +1127,62 @@
         Iterator<Integer> it = ofPorts.iterator();
         return Long.parseLong(it.next().toString());
     }
+
+    @Override
+    public Set<OvsdbPort> getLocalPorts(Iterable<String> ifaceids) {
+        Set<OvsdbPort> ovsdbPorts = new HashSet<OvsdbPort>();
+        OvsdbTableStore tableStore = getTableStore(OvsdbConstant.DATABASENAME);
+        if (tableStore == null) {
+            return null;
+        }
+        OvsdbRowStore rowStore = tableStore.getRows(OvsdbConstant.INTERFACE);
+        if (rowStore == null) {
+            return null;
+        }
+        ConcurrentMap<String, Row> rows = rowStore.getRowStore();
+        for (String uuid : rows.keySet()) {
+            Row row = getRow(OvsdbConstant.DATABASENAME,
+                             OvsdbConstant.INTERFACE, uuid);
+            DatabaseSchema dbSchema = getDatabaseSchema(OvsdbConstant.DATABASENAME);
+            Interface intf = (Interface) TableGenerator
+                    .getTable(dbSchema, row, OvsdbTable.INTERFACE);
+            if (intf == null || getIfaceid(intf) == null) {
+                continue;
+            }
+            String portName = intf.getName();
+            Set<String> ifaceidSet = Sets.newHashSet(ifaceids);
+            if (portName.startsWith("vxlan")
+                    || !ifaceidSet.contains(getIfaceid(intf))) {
+                continue;
+            }
+            long ofPort = getOfPort(intf);
+            if ((ofPort < 0) || (portName == null)) {
+                continue;
+            }
+
+            OvsdbPort ovsdbPort = new OvsdbPort(new OvsdbPortNumber(ofPort),
+                                                new OvsdbPortName(portName));
+            if (ovsdbPort != null) {
+                ovsdbPorts.add(ovsdbPort);
+            }
+        }
+        return ovsdbPorts;
+    }
+
+    private String getIfaceid(Interface intf) {
+        OvsdbMap ovsdbMap = (OvsdbMap) intf.getExternalIdsColumn().data();
+        @SuppressWarnings("unchecked")
+        Map<String, String> externalIds = ovsdbMap.map();
+        if (externalIds.isEmpty()) {
+            log.warn("The external_ids is null");
+            return null;
+        }
+        String ifaceid = externalIds
+                .get(OvsdbConstant.EXTERNAL_ID_INTERFACE_ID);
+        if (ifaceid == null) {
+            log.warn("The ifaceid is null");
+            return null;
+        }
+        return ifaceid;
+    }
 }
diff --git a/ovsdb/ctl/src/main/java/org/onosproject/ovsdb/controller/impl/OvsdbControllerImpl.java b/ovsdb/ctl/src/main/java/org/onosproject/ovsdb/controller/impl/OvsdbControllerImpl.java
index 07100a9..9b48296 100644
--- a/ovsdb/ctl/src/main/java/org/onosproject/ovsdb/controller/impl/OvsdbControllerImpl.java
+++ b/ovsdb/ctl/src/main/java/org/onosproject/ovsdb/controller/impl/OvsdbControllerImpl.java
@@ -220,7 +220,6 @@
                 log.debug("Begin to process table updates uuid: {}, databaseName: {}, tableName: {}",
                           uuid.value(), dbName, tableName);
 
-                Row oldRow = update.getOld(uuid);
                 Row newRow = update.getNew(uuid);
                 if (newRow != null) {
                     clientService.updateOvsdbStore(dbName, tableName,
@@ -228,18 +227,19 @@
 
                     if (OvsdbConstant.INTERFACE.equals(tableName)) {
                         dispatchInterfaceEvent(clientService,
-                                               newRow, null,
+                                               newRow,
                                                OvsdbEvent.Type.PORT_ADDED,
                                                dbSchema);
                     }
                 } else if (update.getOld(uuid) != null) {
-                    clientService.removeRow(dbName, tableName, uuid.value());
-                    if (OvsdbConstant.PORT.equals(tableName)) {
-                        dispatchInterfaceEvent(clientService, null,
-                                               oldRow,
+                    if (OvsdbConstant.INTERFACE.equals(tableName)) {
+                        Row row = clientService.getRow(OvsdbConstant.DATABASENAME, tableName, uuid.value());
+                        dispatchInterfaceEvent(clientService,
+                                               row,
                                           OvsdbEvent.Type.PORT_REMOVED,
                                           dbSchema);
                     }
+                    clientService.removeRow(dbName, tableName, uuid.value());
                 }
             }
         }
@@ -255,13 +255,13 @@
      * @param dbSchema ovsdb database schema
      */
     private void dispatchInterfaceEvent(OvsdbClientService clientService,
-                                        Row newRow, Row oldRow,
+                                        Row row,
                                         Type eventType,
                                         DatabaseSchema dbSchema) {
 
         long dpid = getDataPathid(clientService, dbSchema);
         Interface intf = (Interface) TableGenerator
-                .getTable(dbSchema, newRow, OvsdbTable.INTERFACE);
+                .getTable(dbSchema, row, OvsdbTable.INTERFACE);
         if (intf == null) {
             return;
         }