Moves flat jump rules from OpenstackSwitchingHandler to OpenstackFlowRuleManager.

Change-Id: I88059fa5f2868bd5e9f08f2fafd5e3bd57d6f8f4
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
index 1858ab9..5608bce 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
@@ -16,12 +16,15 @@
 
 package org.onosproject.openstacknetworking.impl;
 
+import org.onlab.packet.Ethernet;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.DefaultFlowRule;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -42,14 +45,20 @@
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.onosproject.openstacknode.api.OpenstackPhyInterface;
 import org.slf4j.Logger;
 
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_UPSTREAM_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -80,6 +89,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected OpenstackNodeService osNodeService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected DeviceService deviceService;
+
     private final ExecutorService deviceEventExecutor =
             Executors.newSingleThreadExecutor(groupedThreads(
                     getClass().getSimpleName(), "device-event"));
@@ -229,6 +241,65 @@
                                 Constants.VTAP_FLAT_OUTBOUND_TABLE);
         connectTables(deviceId, Constants.VTAP_FLAT_OUTBOUND_TABLE,
                                 Constants.FLAT_TABLE);
+
+        // for FLAT table drop
+        setUpTableMissEntry(deviceId, Constants.FLAT_TABLE);
+
+        // for FLAT jump rules
+        if (!osNodeService.node(deviceId).phyIntfs().isEmpty()) {
+            setFlatJumpRules(deviceId);
+        }
+    }
+
+    private void setFlatJumpRules(DeviceId deviceId) {
+        osNodeService.node(deviceId)
+                     .phyIntfs()
+                     .forEach(phyInterface ->
+                             setFlatJumpRulesForPhyIntf(deviceId, phyInterface));
+    }
+
+    private void setFlatJumpRulesForPhyIntf(DeviceId deviceId,
+                                            OpenstackPhyInterface phyInterface) {
+        Optional<Port> phyPort = deviceService.getPorts(deviceId).stream()
+                .filter(port ->
+                        Objects.equals(port.annotations().value(PORT_NAME), phyInterface.intf()))
+                .findAny();
+
+        phyPort.ifPresent(port -> {
+            TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+            selector.matchInPort(port.number())
+                    .matchEthType(Ethernet.TYPE_IPV4);
+
+            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+            treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
+            FlowRule flowRuleForIp = DefaultFlowRule.builder()
+                    .forDevice(deviceId)
+                    .withSelector(selector.build())
+                    .withTreatment(treatment.build())
+                    .withPriority(PRIORITY_FLAT_JUMP_UPSTREAM_RULE)
+                    .fromApp(appId)
+                    .makePermanent()
+                    .forTable(DHCP_TABLE)
+                    .build();
+
+            applyRule(flowRuleForIp, true);
+
+            selector = DefaultTrafficSelector.builder();
+            selector.matchInPort(port.number())
+                    .matchEthType(Ethernet.TYPE_ARP);
+
+            FlowRule flowRuleForArp = DefaultFlowRule.builder()
+                    .forDevice(deviceId)
+                    .withSelector(selector.build())
+                    .withTreatment(treatment.build())
+                    .withPriority(PRIORITY_FLAT_JUMP_UPSTREAM_RULE)
+                    .fromApp(appId)
+                    .makePermanent()
+                    .forTable(DHCP_TABLE)
+                    .build();
+
+            applyRule(flowRuleForArp, true);
+        });
     }
 
     private void setupJumpTable(DeviceId deviceId) {
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index 0fab37e..71dbe5a 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -69,7 +69,6 @@
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_DOWNSTREAM_RULE;
-import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_JUMP_UPSTREAM_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_UPSTREAM_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
@@ -189,34 +188,6 @@
             log.warn("The port number does not exist");
             return;
         }
-
-        selector = DefaultTrafficSelector.builder();
-        selector.matchInPort(portNumber)
-                .matchEthType(Ethernet.TYPE_IPV4)
-                .matchIPDst(port.ipAddress().toIpPrefix());
-
-        osFlowRuleService.setRule(
-                appId,
-                port.deviceId(),
-                selector.build(),
-                treatment.build(),
-                PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
-                DHCP_TABLE,
-                install);
-
-        selector = DefaultTrafficSelector.builder();
-        selector.matchInPort(portNumber)
-                .matchEthType(Ethernet.TYPE_ARP)
-                .matchArpTpa(port.ipAddress().getIp4Address());
-
-        osFlowRuleService.setRule(
-                appId,
-                port.deviceId(),
-                selector.build(),
-                treatment.build(),
-                PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
-                DHCP_TABLE,
-                install);
     }
 
     private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java
index ed73636..bd982f2 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java
@@ -23,6 +23,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.junit.TestUtils;
+import org.onlab.packet.IpAddress;
 import org.onosproject.cluster.ClusterServiceAdapter;
 import org.onosproject.cluster.LeadershipServiceAdapter;
 import org.onosproject.core.ApplicationId;
@@ -38,6 +39,9 @@
 import org.onosproject.net.flow.FlowRuleServiceAdapter;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.openstacknode.api.DefaultOpenstackNode;
+import org.onosproject.openstacknode.api.NodeState;
+import org.onosproject.openstacknode.api.OpenstackNode;
 
 import java.util.List;
 import java.util.Map;
@@ -189,7 +193,7 @@
         fros = Sets.newConcurrentHashSet();
 
         target.initializePipeline(DEVICE_ID);
-        assertEquals("Flow Rule size was not match", 12, fros.size());
+        assertEquals("Flow Rule size was not match", 13, fros.size());
 
         Map<Integer, Integer> fromToTableMap = Maps.newConcurrentMap();
         fromToTableMap.put(STAT_INBOUND_TABLE, VTAP_INBOUND_TABLE);
@@ -204,7 +208,7 @@
         fromToTableMap.put(VTAP_FLAT_OUTBOUND_TABLE, FLAT_TABLE);
 
         fros.stream().map(FlowRuleOperation::rule).forEach(fr -> {
-            if (fr.tableId() != JUMP_TABLE) {
+            if (fr.tableId() != JUMP_TABLE && fr.tableId() != FLAT_TABLE) {
                 assertEquals("To Table did not match,",
                         fromToTableMap.get(fr.tableId()),
                         fr.treatment().tableTransition().tableId());
@@ -229,6 +233,16 @@
     }
 
     private class TestOpenstackNodeService extends OpenstackNodeServiceAdapter {
+        @Override
+        public OpenstackNode node(DeviceId deviceId) {
+            return DefaultOpenstackNode.builder()
+                    .hostname("host")
+                    .type(OpenstackNode.NodeType.COMPUTE)
+                    .state(NodeState.COMPLETE)
+                    .managementIp(IpAddress.valueOf("1.1.1.1"))
+                    .dataIp(IpAddress.valueOf("1.1.1.1"))
+                    .build();
+        }
     }
 
     private class TestFlowRuleService extends FlowRuleServiceAdapter {