[ONOS-6484] Implements OpenStack Pipeline at the application layer.

Change-Id: I9aeca05936cf846b86ffafc856f6e84697f5e94d
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
index f42923c..daedcc2 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
@@ -46,4 +46,5 @@
     public static final int JUMP_TABLE = 2;
     public static final int ROUTING_TABLE = 3;
     public static final int FORWARDING_TABLE = 4;
+    public static final int GW_COMMON_TABLE = 0;
 }
\ No newline at end of file
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/OpenstackFlowRuleService.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/OpenstackFlowRuleService.java
index 01da935..daed587 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/OpenstackFlowRuleService.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/api/OpenstackFlowRuleService.java
@@ -16,21 +16,32 @@
 package org.onosproject.openstacknetworking.api;
 
 
+import org.onosproject.core.ApplicationId;
 import org.onosproject.net.DeviceId;
-import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
 
 /**
  * Service for setting flow rules.
  *
  */
 public interface OpenstackFlowRuleService {
-
     /**
-     * Sets flow rules.
+     * Sets the flow rule.
      *
-     * @param deviceId Device ID
-     * @param forwardingObjective flow rule container
-     * @param tableType table type for the flow rules
+     * @param appId application ID
+     * @param deviceId  device ID
+     * @param selector matches of the flow rule
+     * @param treatment actions of the flow rule
+     * @param priority priority of the flow rule
+     * @param tableType table number to put the flow rule
+     * @param install add the rule if true, remove it otherwise
      */
-    void forward(DeviceId deviceId, ForwardingObjective forwardingObjective, int tableType);
+    void setRule(ApplicationId appId,
+              DeviceId deviceId,
+              TrafficSelector selector,
+              TrafficTreatment treatment,
+              int priority,
+              int tableType,
+              boolean install);
 }
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
index 6e8e7e0..4f7ead7 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
@@ -34,9 +34,6 @@
 import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.onosproject.net.flowobjective.Objective;
 import org.onosproject.openstacknetworking.api.Constants;
 import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknode.OpenstackNode;
@@ -63,7 +60,7 @@
 
     private static final int DROP_PRIORITY = 0;
     private static final int HIGH_PRIORITY = 30000;
-    private static final int FLOW_RULE_TIME_OUT = 60;
+    private static final int TIMEOUT_SNAT_RULE = 60;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected FlowRuleService flowRuleService;
@@ -97,35 +94,34 @@
         log.info("Stopped");
     }
 
+
     @Override
-    public void forward(DeviceId deviceId, ForwardingObjective forwardingObjective, int tableType) {
-        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+    public void setRule(ApplicationId appId,
+                               DeviceId deviceId,
+                               TrafficSelector selector,
+                               TrafficTreatment treatment,
+                               int priority,
+                               int tableType,
+                               boolean install) {
 
-        forwardingObjective.treatment().allInstructions().stream()
-                .filter(i -> i.type() != Instruction.Type.NOACTION).forEach(treatment::add);
-
-        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+        FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder()
                 .forDevice(deviceId)
-                .withSelector(forwardingObjective.selector())
-                .withTreatment(treatment.build())
-                .withPriority(forwardingObjective.priority())
-                .fromApp(forwardingObjective.appId())
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .withPriority(priority)
+                .fromApp(appId)
                 .forTable(tableType);
 
-        if (forwardingObjective.permanent()) {
-            ruleBuilder.makePermanent();
+        if (priority == Constants.PRIORITY_SNAT_RULE) {
+            flowRuleBuilder.makeTemporary(TIMEOUT_SNAT_RULE);
         } else {
-            ruleBuilder.makeTemporary(FLOW_RULE_TIME_OUT);
+            flowRuleBuilder.makePermanent();
         }
 
-        if (forwardingObjective.op().equals(Objective.Operation.ADD)) {
-            applyRules(true, ruleBuilder.build());
-        } else {
-            applyRules(false, ruleBuilder.build());
-        }
+        applyRule(flowRuleBuilder.build(), install);
     }
 
-    private void applyRules(boolean install, FlowRule flowRule) {
+    private void applyRule(FlowRule flowRule, boolean install) {
         FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
 
         flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
@@ -146,7 +142,6 @@
     private void initializePipeline(DeviceId deviceId) {
         connectTables(deviceId, Constants.SRC_VNI_TABLE, Constants.ACL_TABLE);
         connectTables(deviceId, Constants.ACL_TABLE, Constants.JUMP_TABLE);
-        setUpTableMissEntry(deviceId, Constants.ACL_TABLE);
         setupJumpTable(deviceId);
     }
 
@@ -166,7 +161,7 @@
                 .forTable(fromTable)
                 .build();
 
-        applyRules(true, flowRule);
+        applyRule(flowRule, true);
     }
 
     private void setUpTableMissEntry(DeviceId deviceId, int table) {
@@ -185,7 +180,7 @@
                 .forTable(table)
                 .build();
 
-        applyRules(true, flowRule);
+        applyRule(flowRule, true);
     }
 
     private void setupJumpTable(DeviceId deviceId) {
@@ -205,7 +200,7 @@
                 .forTable(Constants.JUMP_TABLE)
                 .build();
 
-        applyRules(true, flowRule);
+        applyRule(flowRule, true);
 
         selector = DefaultTrafficSelector.builder();
         treatment = DefaultTrafficTreatment.builder();
@@ -222,7 +217,7 @@
                 .forTable(Constants.JUMP_TABLE)
                 .build();
 
-        applyRules(true, flowRule);
+        applyRule(flowRule, true);
     }
 
     private class InternalOpenstackNodeListener implements OpenstackNodeListener {
@@ -236,7 +231,7 @@
                 case COMPLETE:
                     deviceEventExecutor.execute(() -> {
                         log.info("COMPLETE node {} is detected", osNode.hostname());
-
+                        processCompleteNode(event.subject());
                     });
                     break;
                 case INCOMPLETE:
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index 6f1cc4b..f1fdf29 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -36,15 +36,14 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.openstacknetworking.api.Constants;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortService;
+import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
 import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
 import org.onosproject.openstacknetworking.api.OpenstackRouterService;
-import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknode.OpenstackNodeEvent;
 import org.onosproject.openstacknode.OpenstackNodeListener;
 import org.onosproject.openstacknode.OpenstackNodeService;
@@ -61,7 +60,10 @@
 
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.openstacknetworking.api.Constants.*;
+import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLOATING_EXTERNAL;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLOATING_INTERNAL;
 import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
 import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
 
@@ -83,9 +85,6 @@
     protected DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowObjectiveService flowObjectiveService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected LeadershipService leadershipService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -103,6 +102,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenstackNetworkService osNetworkService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected OpenstackFlowRuleService osFlowRuleService;
+
     private final ExecutorService eventExecutor = newSingleThreadExecutor(
             groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
     private final OpenstackRouterListener floatingIpLisener = new InternalFloatingIpLisener();
@@ -197,14 +199,13 @@
                     throw new IllegalStateException(error);
             }
 
-            RulePopulatorUtil.setRule(
-                    flowObjectiveService,
+            osFlowRuleService.setRule(
                     appId,
                     gnodeId,
                     externalSelector,
                     externalBuilder.build(),
-                    ForwardingObjective.Flag.VERSATILE,
                     PRIORITY_FLOATING_EXTERNAL,
+                    GW_COMMON_TABLE,
                     install);
 
             // access from one VM to the other via floating IP
@@ -241,14 +242,13 @@
                     throw new IllegalStateException(error);
             }
 
-            RulePopulatorUtil.setRule(
-                    flowObjectiveService,
+            osFlowRuleService.setRule(
                     appId,
                     gnodeId,
                     internalSelector,
                     internalBuilder.build(),
-                    ForwardingObjective.Flag.VERSATILE,
                     PRIORITY_FLOATING_INTERNAL,
+                    GW_COMMON_TABLE,
                     install);
         });
     }
@@ -285,14 +285,13 @@
                 tBuilder.popVlan();
             }
 
-            RulePopulatorUtil.setRule(
-                    flowObjectiveService,
+            osFlowRuleService.setRule(
                     appId,
                     gnodeId,
                     sBuilder.build(),
                     tBuilder.setOutput(osNodeService.externalPort(gnodeId).get()).build(),
-                    ForwardingObjective.Flag.VERSATILE,
                     PRIORITY_FLOATING_EXTERNAL,
+                    GW_COMMON_TABLE,
                     install);
         });
     }
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
index b004ee7..e0b5ccb 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
@@ -41,9 +41,8 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.openstacknetworking.api.Constants;
+import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
 import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
@@ -53,7 +52,6 @@
 import org.onosproject.openstacknode.OpenstackNodeListener;
 import org.onosproject.openstacknode.OpenstackNodeService;
 import org.onosproject.openstacknode.OpenstackNodeService.NetworkMode;
-
 import org.openstack4j.model.network.ExternalGateway;
 import org.openstack4j.model.network.Network;
 import org.openstack4j.model.network.NetworkType;
@@ -72,7 +70,13 @@
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.AnnotationKeys.PORT_MAC;
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
-import static org.onosproject.openstacknetworking.api.Constants.*;
+import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_EXTERNAL_ROUTING_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ICMP_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
 import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
 
 /**
@@ -98,9 +102,6 @@
     protected ClusterService clusterService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowObjectiveService flowObjectiveService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenstackNodeService osNodeService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -112,6 +113,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected OpenstackFlowRuleService osFlowRuleService;
+
     private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
             groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
     private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
@@ -344,14 +348,13 @@
                 .setOutput(PortNumber.CONTROLLER)
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 deviceId,
                 selector,
                 treatment,
-                ForwardingObjective.Flag.VERSATILE,
                 PRIORITY_ICMP_RULE,
+                Constants.GW_COMMON_TABLE,
                 install);
     }
 
@@ -371,16 +374,16 @@
 
                 treatment = DefaultTrafficTreatment.builder()
                         .setTunnelId(Long.parseLong(dstSegmentId))
+                        .transition(FORWARDING_TABLE)
                         .build();
 
-                RulePopulatorUtil.setRule(
-                        flowObjectiveService,
+                osFlowRuleService.setRule(
                         appId,
                         deviceId,
                         selector,
                         treatment,
-                        ForwardingObjective.Flag.SPECIFIC,
                         PRIORITY_INTERNAL_ROUTING_RULE,
+                        ROUTING_TABLE,
                         install);
 
                 selector = DefaultTrafficSelector.builder()
@@ -392,16 +395,16 @@
 
                 treatment = DefaultTrafficTreatment.builder()
                         .setTunnelId(Long.parseLong(dstSegmentId))
+                        .transition(FORWARDING_TABLE)
                         .build();
 
-                RulePopulatorUtil.setRule(
-                        flowObjectiveService,
+                osFlowRuleService.setRule(
                         appId,
                         deviceId,
                         selector,
                         treatment,
-                        ForwardingObjective.Flag.SPECIFIC,
                         PRIORITY_INTERNAL_ROUTING_RULE,
+                        ROUTING_TABLE,
                         install);
                 break;
             case VLAN:
@@ -414,16 +417,16 @@
 
                 treatment = DefaultTrafficTreatment.builder()
                         .setVlanId(VlanId.vlanId(dstSegmentId))
+                        .transition(FORWARDING_TABLE)
                         .build();
 
-                RulePopulatorUtil.setRule(
-                        flowObjectiveService,
+                osFlowRuleService.setRule(
                         appId,
                         deviceId,
                         selector,
                         treatment,
-                        ForwardingObjective.Flag.SPECIFIC,
                         PRIORITY_INTERNAL_ROUTING_RULE,
+                        ROUTING_TABLE,
                         install);
 
                 selector = DefaultTrafficSelector.builder()
@@ -435,16 +438,16 @@
 
                 treatment = DefaultTrafficTreatment.builder()
                         .setVlanId(VlanId.vlanId(dstSegmentId))
+                        .transition(FORWARDING_TABLE)
                         .build();
 
-                RulePopulatorUtil.setRule(
-                        flowObjectiveService,
+                osFlowRuleService.setRule(
                         appId,
                         deviceId,
                         selector,
                         treatment,
-                        ForwardingObjective.Flag.SPECIFIC,
                         PRIORITY_INTERNAL_ROUTING_RULE,
+                        ROUTING_TABLE,
                         install);
                 break;
             default:
@@ -488,14 +491,13 @@
                 .group(groupId)
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 deviceId,
                 sBuilder.build(),
                 treatment,
-                ForwardingObjective.Flag.SPECIFIC,
                 PRIORITY_EXTERNAL_ROUTING_RULE,
+                ROUTING_TABLE,
                 install);
     }
 
@@ -530,14 +532,13 @@
 
         tBuilder.setOutput(PortNumber.CONTROLLER);
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 deviceId,
                 sBuilder.build(),
                 tBuilder.build(),
-                ForwardingObjective.Flag.VERSATILE,
                 PRIORITY_EXTERNAL_ROUTING_RULE,
+                Constants.GW_COMMON_TABLE,
                 install);
     }
 
@@ -569,14 +570,13 @@
                 .group(groupId)
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 deviceId,
                 selector,
                 treatment,
-                ForwardingObjective.Flag.SPECIFIC,
                 PRIORITY_SWITCHING_RULE,
+                ROUTING_TABLE,
                 install);
     }
 
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
index 05b919a..9d62a34 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
@@ -37,9 +37,6 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.packet.DefaultOutboundPacket;
 import org.onosproject.net.packet.InboundPacket;
 import org.onosproject.net.packet.PacketContext;
@@ -47,8 +44,9 @@
 import org.onosproject.net.packet.PacketService;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortService;
-import org.onosproject.openstacknetworking.api.OpenstackRouterService;
+import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
+import org.onosproject.openstacknetworking.api.OpenstackRouterService;
 import org.onosproject.openstacknode.OpenstackNodeService;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.ConsistentMap;
@@ -71,7 +69,11 @@
 
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.openstacknetworking.api.Constants.*;
+import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_EXTERNAL_ROUTER_MAC;
+import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC;
+import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SNAT_RULE;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -84,7 +86,6 @@
 
     private static final String ERR_PACKETIN = "Failed to handle packet in: ";
     private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
-    private static final int TIME_OUT_SNAT_RULE = 120;
     private static final long TIME_OUT_SNAT_PORT_MS = 120 * 1000;
     private static final int TP_PORT_MINIMUM_NUM = 65000;
     private static final int TP_PORT_MAXIMUM_NUM = 65535;
@@ -102,9 +103,6 @@
     protected StorageService storageService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowObjectiveService flowObjectiveService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -119,6 +117,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenstackRouterService osRouterService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected OpenstackFlowRuleService osFlowRuleService;
+
     private final ExecutorService eventExecutor = newSingleThreadExecutor(
             groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
     private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
@@ -344,16 +345,14 @@
                     throw new IllegalStateException(error);
             }
 
-            ForwardingObjective fo = DefaultForwardingObjective.builder()
-                    .withSelector(sBuilder.build())
-                    .withTreatment(tmpBuilder.build())
-                    .withFlag(ForwardingObjective.Flag.VERSATILE)
-                    .withPriority(PRIORITY_SNAT_RULE)
-                    .makeTemporary(TIME_OUT_SNAT_RULE)
-                    .fromApp(appId)
-                    .add();
-
-            flowObjectiveService.forward(deviceId, fo);
+            osFlowRuleService.setRule(
+                    appId,
+                    deviceId,
+                    sBuilder.build(),
+                    tmpBuilder.build(),
+                    PRIORITY_SNAT_RULE,
+                    GW_COMMON_TABLE,
+                    true);
         });
     }
 
@@ -410,16 +409,15 @@
             TrafficTreatment.Builder tmpBuilder =
                     DefaultTrafficTreatment.builder(tBuilder.build());
             tmpBuilder.setOutput(osNodeService.externalPort(deviceId).get());
-            ForwardingObjective fo = DefaultForwardingObjective.builder()
-                    .withSelector(sBuilder.build())
-                    .withTreatment(tmpBuilder.build())
-                    .withFlag(ForwardingObjective.Flag.VERSATILE)
-                    .withPriority(PRIORITY_SNAT_RULE)
-                    .makeTemporary(TIME_OUT_SNAT_RULE)
-                    .fromApp(appId)
-                    .add();
 
-            flowObjectiveService.forward(deviceId, fo);
+            osFlowRuleService.setRule(
+                    appId,
+                    deviceId,
+                    sBuilder.build(),
+                    tmpBuilder.build(),
+                    PRIORITY_SNAT_RULE,
+                    GW_COMMON_TABLE,
+                    true);
         });
     }
 
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index c41c6dc..7664429 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -38,13 +38,12 @@
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
 import org.onosproject.openstacknetworking.api.InstancePortListener;
 import org.onosproject.openstacknetworking.api.InstancePortService;
+import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
@@ -67,6 +66,8 @@
 
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.JUMP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ACL_RULE;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -101,7 +102,7 @@
     protected OpenstackSecurityGroupService securityGroupService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowObjectiveService flowObjectiveService;
+    protected OpenstackFlowRuleService osFlowRuleService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ComponentConfigService configService;
@@ -196,17 +197,24 @@
 
     private void populateSecurityGroupRule(SecurityGroupRule sgRule, InstancePort instPort,
                                            IpPrefix remoteIp, boolean install) {
-        ForwardingObjective.Builder foBuilder = buildFlowObjective(sgRule,
-                Ip4Address.valueOf(instPort.ipAddress().toInetAddress()), remoteIp);
-        if (foBuilder == null) {
+        Ip4Address vmIp = Ip4Address.valueOf(instPort.ipAddress().toInetAddress());
+        if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
+            // do nothing if the remote IP is my IP
             return;
         }
 
-        if (install) {
-            flowObjectiveService.forward(instPort.deviceId(), foBuilder.add());
-        } else {
-            flowObjectiveService.forward(instPort.deviceId(), foBuilder.remove());
-        }
+        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+        buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().transition(JUMP_TABLE).build();
+
+        osFlowRuleService.setRule(appId,
+                instPort.deviceId(),
+                sBuilder.build(),
+                treatment,
+                PRIORITY_ACL_RULE,
+                ACL_TABLE,
+                install);
     }
 
     /**
@@ -230,25 +238,6 @@
         return Collections.unmodifiableSet(remoteInstPorts);
     }
 
-    private ForwardingObjective.Builder buildFlowObjective(SecurityGroupRule sgRule,
-                                                           Ip4Address vmIp,
-                                                           IpPrefix remoteIp) {
-        if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
-            // do nothing if the remote IP is my IP
-            return null;
-        }
-
-        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
-        buildMatchs(sBuilder, sgRule, vmIp, remoteIp);
-
-        return DefaultForwardingObjective.builder()
-                .withSelector(sBuilder.build())
-                .withTreatment(DefaultTrafficTreatment.builder().build())
-                .withPriority(PRIORITY_ACL_RULE)
-                .withFlag(ForwardingObjective.Flag.SPECIFIC)
-                .fromApp(appId);
-    }
-
     private void buildMatchs(TrafficSelector.Builder sBuilder, SecurityGroupRule sgRule,
                              Ip4Address vmIp, IpPrefix remoteIp) {
         buildMatchEthType(sBuilder, sgRule.getEtherType());
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index 975096f..10b1776 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -32,12 +32,11 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
 import org.onosproject.openstacknetworking.api.InstancePortListener;
 import org.onosproject.openstacknetworking.api.InstancePortService;
+import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknode.OpenstackNodeService;
 import org.openstack4j.model.network.Network;
@@ -47,7 +46,12 @@
 
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.openstacknetworking.api.Constants.*;
+import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.SRC_VNI_TABLE;
 import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
 import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -74,7 +78,7 @@
     protected DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowObjectiveService flowObjectiveService;
+    protected OpenstackFlowRuleService osFlowRuleService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected InstancePortService instancePortService;
@@ -134,14 +138,13 @@
                 .setOutput(instPort.portNumber())
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 instPort.deviceId(),
                 selector,
                 treatment,
-                ForwardingObjective.Flag.SPECIFIC,
                 PRIORITY_SWITCHING_RULE,
+                FORWARDING_TABLE,
                 install);
 
         // switching rules for the instPorts in the remote node
@@ -158,14 +161,13 @@
                             .setOutput(osNodeService.tunnelPort(osNode.intBridge()).get())
                             .build();
 
-                    RulePopulatorUtil.setRule(
-                            flowObjectiveService,
+                    osFlowRuleService.setRule(
                             appId,
                             osNode.intBridge(),
                             selector,
                             treatmentToRemote,
-                            ForwardingObjective.Flag.SPECIFIC,
                             PRIORITY_SWITCHING_RULE,
+                            FORWARDING_TABLE,
                             install);
                 });
     }
@@ -184,14 +186,13 @@
                 .setOutput(instPort.portNumber())
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 instPort.deviceId(),
                 selector,
                 treatment,
-                ForwardingObjective.Flag.SPECIFIC,
                 PRIORITY_SWITCHING_RULE,
+                FORWARDING_TABLE,
                 install);
 
         // switching rules for the instPorts in the remote node
@@ -204,14 +205,13 @@
                                     .setOutput(osNodeService.vlanPort(osNode.intBridge()).get())
                                     .build();
 
-                    RulePopulatorUtil.setRule(
-                            flowObjectiveService,
+                    osFlowRuleService.setRule(
                             appId,
                             osNode.intBridge(),
                             selector,
                             treatmentToRemote,
-                            ForwardingObjective.Flag.SPECIFIC,
                             PRIORITY_SWITCHING_RULE,
+                            FORWARDING_TABLE,
                             install);
                 });
 
@@ -225,16 +225,16 @@
 
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                 .setTunnelId(getVni(instPort))
+                .transition(ACL_TABLE)
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 instPort.deviceId(),
                 selector,
                 treatment,
-                ForwardingObjective.Flag.SPECIFIC,
                 PRIORITY_TUNNEL_TAG_RULE,
+                SRC_VNI_TABLE,
                 install);
     }
 
@@ -247,16 +247,16 @@
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                 .pushVlan()
                 .setVlanId(getVlanId(instPort))
+                .transition(ACL_TABLE)
                 .build();
 
-        RulePopulatorUtil.setRule(
-                flowObjectiveService,
+        osFlowRuleService.setRule(
                 appId,
                 instPort.deviceId(),
                 selector,
                 treatment,
-                ForwardingObjective.Flag.SPECIFIC,
                 PRIORITY_TUNNEL_TAG_RULE,
+                SRC_VNI_TABLE,
                 install);
 
     }
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java
index 3d4c385..8e27762 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java
@@ -16,18 +16,12 @@
 package org.onosproject.openstacknetworking.impl;
 
 import org.onlab.packet.Ip4Address;
-import org.onosproject.core.ApplicationId;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
 import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.instructions.ExtensionPropertyException;
 import org.onosproject.net.flow.instructions.ExtensionTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.slf4j.Logger;
 
 import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
@@ -74,38 +68,4 @@
             return null;
         }
     }
-
-    /**
-     * Adds flow rules with the supplied information.
-     *
-     * @param flowObjectiveService flow objective service
-     * @param appId application id
-     * @param deviceId device id to remove this flow rule
-     * @param selector traffic selector
-     * @param treatment traffic treatment
-     * @param flag flag
-     * @param priority priority
-     * @param install populate flows if true, remove them otherwise
-     */
-    public static void setRule(FlowObjectiveService flowObjectiveService,
-                               ApplicationId appId,
-                               DeviceId deviceId,
-                               TrafficSelector selector,
-                               TrafficTreatment treatment,
-                               ForwardingObjective.Flag flag,
-                               int priority,
-                               boolean install) {
-        ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
-                .withSelector(selector)
-                .withTreatment(treatment)
-                .withFlag(flag)
-                .withPriority(priority)
-                .fromApp(appId);
-
-        if (install) {
-            flowObjectiveService.forward(deviceId, foBuilder.add());
-        } else {
-            flowObjectiveService.forward(deviceId, foBuilder.remove());
-        }
-    }
 }