[ONOS-3948] Seperate mgmt and data network in OpenstackSwitching/RoutingService

- Supports the seperation of management and data network

Change-Id: I178dbe2af241123c5181f94a7b46fc15b4cb37c7
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingConfig.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingConfig.java
index 74f563f..7c9f126 100644
--- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingConfig.java
+++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingConfig.java
@@ -15,10 +15,16 @@
  */
 package org.onosproject.openstacknetworking.routing;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Maps;
+import org.onlab.packet.Ip4Address;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.Config;
 import org.slf4j.Logger;
 
+import java.util.Map;
+
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -31,6 +37,35 @@
     public static final String GATEWAY_BRIDGE_ID = "gatewayBridgeId";
     public static final String GATEWAY_EXTERNAL_INTERFACE_NAME = "gatewayExternalInterfaceName";
     public static final String GATEWAY_EXTERNAL_INTERFACE_MAC = "gatewayExternalInterfaceMac";
+    public static final String NODES = "nodes";
+    public static final String DATAPLANE_IP = "dataPlaneIp";
+    public static final String BRIDGE_ID = "bridgeId";
+
+
+    /**
+     * Returns the data plane IP map of nodes read from network config.
+     *
+     * @return data plane IP map
+     */
+    public Map<DeviceId, Ip4Address> nodes() {
+        Map<DeviceId, Ip4Address> nodeMap = Maps.newHashMap();
+
+        JsonNode jsonNodes = object.get(NODES);
+        if (jsonNodes == null) {
+            log.error("There's no node information");
+            return null;
+        }
+
+        jsonNodes.forEach(jsonNode -> {
+            try {
+                nodeMap.putIfAbsent(DeviceId.deviceId(jsonNode.path(BRIDGE_ID).asText()),
+                        Ip4Address.valueOf(jsonNode.path(DATAPLANE_IP).asText()));
+            } catch (IllegalArgumentException | NullPointerException e) {
+                log.error("Failed to read {}", e.toString());
+            }
+        });
+        return nodeMap;
+    }
 
     /**
      * Returns physical router mac.
@@ -38,7 +73,7 @@
      * @return physical router mac
      */
     public String physicalRouterMac() {
-        return this.get("physicalRouterMac", "");
+        return this.get(PHYSICAL_ROUTER_MAC, "");
     }
 
     /**
@@ -47,7 +82,7 @@
      * @return bridge id
      */
     public String gatewayBridgeId() {
-        return this.get("gatewayBridgeId", "");
+        return this.get(GATEWAY_BRIDGE_ID, "");
     }
 
     /**
@@ -56,7 +91,7 @@
      * @return external interface name
      */
     public String gatewayExternalInterfaceName() {
-        return this.get("gatewayExternalInterfaceName", "");
+        return this.get(GATEWAY_EXTERNAL_INTERFACE_NAME, "");
     }
 
     /**
@@ -65,6 +100,6 @@
      * @return external interface mac
      */
     public String gatewayExternalInterfaceMac() {
-        return this.get("gatewayExternalInterfaceMac", "");
+        return this.get(GATEWAY_EXTERNAL_INTERFACE_MAC, "");
     }
 }
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
index 52a74c5..891b622 100644
--- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
+++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java
@@ -62,6 +62,8 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
@@ -108,6 +110,7 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService storageService;
 
+
     private ApplicationId appId;
     private ConsistentMap<Integer, String> tpPortNumMap; // Map<PortNum, allocated VM`s Mac & destionation Ip address>
     private ConsistentMap<String, OpenstackFloatingIP> floatingIpMap; // Map<FloatingIp`s Id, FloatingIp object>
@@ -117,6 +120,7 @@
     private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface";
     private static final String FLOATING_IP_MAP_NAME = "openstackrouting-floatingip";
     private static final String TP_PORT_MAP_NAME = "openstackrouting-portnum";
+    private static final String COLON = ":";
     private static final int PNAT_PORT_EXPIRE_TIME = 1200 * 1000;
     private static final int TP_PORT_MINIMUM_NUM = 1024;
     private static final int TP_PORT_MAXIMUM_NUM = 65535;
@@ -154,6 +158,7 @@
     private OpenstackIcmpHandler openstackIcmpHandler;
     private OpenstackRoutingArpHandler openstackArpHandler;
     private OpenstackRoutingRulePopulator rulePopulator;
+    private Map<DeviceId, Ip4Address> computeNodeMap;
 
     @Activate
     protected void activate() {
@@ -314,7 +319,7 @@
     }
 
     private void reloadInitL3Rules() {
-        l3EventExecutorService.submit(() ->
+        l3EventExecutorService.execute(() ->
                         openstackService.ports()
                                 .stream()
                                 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
@@ -359,7 +364,7 @@
                 switch (iPacket.getProtocol()) {
                     case IPv4.PROTOCOL_ICMP:
 
-                        icmpEventExecutorService.submit(() ->
+                        icmpEventExecutorService.execute(() ->
                                 openstackIcmpHandler.processIcmpPacket(context, ethernet));
                         break;
                     case IPv4.PROTOCOL_UDP:
@@ -371,20 +376,21 @@
                         }
                     default:
                         int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress());
-                        Port port =
+                        Optional<Port> port =
                                 getExternalPort(pkt.receivedFrom().deviceId(), config.gatewayExternalInterfaceName());
-                        if (port == null) {
+
+                        if (!port.isPresent()) {
                             log.warn("There`s no external interface");
-                            break;
+                        } else {
+                            OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(),
+                                    Ip4Address.valueOf(iPacket.getSourceAddress()));
+                            l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context,
+                                    portNum, openstackPort, port.get(), config));
                         }
-                        OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(),
-                                Ip4Address.valueOf(iPacket.getSourceAddress()));
-                        l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context,
-                                portNum, openstackPort, port, config));
                         break;
                 }
             } else if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
-                arpEventExecutorService.submit(() ->
+                arpEventExecutorService.execute(() ->
                         openstackArpHandler.processArpPacketFromRouter(context, ethernet));
             }
         }
@@ -395,7 +401,7 @@
                 clearPortNumMap();
                 portNum = findUnusedPortNum();
             }
-            tpPortNumMap.put(portNum, sourceMac.toString().concat(":").concat(String.valueOf(destinationAddress)));
+            tpPortNumMap.put(portNum, sourceMac.toString().concat(COLON).concat(String.valueOf(destinationAddress)));
             return portNum;
         }
 
@@ -418,12 +424,11 @@
         });
     }
 
-    private Port getExternalPort(DeviceId deviceId, String interfaceName) {
+    private Optional<Port> getExternalPort(DeviceId deviceId, String interfaceName) {
         return deviceService.getPorts(deviceId)
                 .stream()
                 .filter(p -> p.annotations().value(PORT_NAME).equals(interfaceName))
-                .findAny()
-                .orElse(null);
+                .findAny();
     }
 
     private void checkExternalConnection(OpenstackRouter router,
@@ -436,33 +441,26 @@
             log.debug("Not satisfied to set pnat configuration");
             return;
         }
-        if (router.id() == null) {
-            interfaces.forEach(i -> initiateL3Rule(getRouterfromExternalIp(externalIp), i));
-        } else {
-            interfaces.forEach(i -> initiateL3Rule(router, i));
-        }
-
+        interfaces.forEach(this::initiateL3Rule);
     }
 
-    private OpenstackRouter getRouterfromExternalIp(Ip4Address externalIp) {
-        OpenstackRouter router = getExternalRouter(true)
+    private Optional<OpenstackRouter> getRouterfromExternalIp(Ip4Address externalIp) {
+        return getExternalRouter(true)
                 .stream()
                 .filter(r -> r.gatewayExternalInfo()
                         .externalFixedIps()
                         .values()
                         .stream()
-                        .findFirst()
-                        .orElse(null)
+                        .findAny()
+                        .get()
                         .equals(externalIp))
-                .findAny()
-                .orElse(null);
-        return checkNotNull(router);
+                .findAny();
     }
 
-    private void initiateL3Rule(OpenstackRouter router, OpenstackRouterInterface routerInterface) {
+    private void initiateL3Rule(OpenstackRouterInterface routerInterface) {
         long vni = Long.parseLong(openstackService.network(openstackService
                 .port(routerInterface.portId()).networkId()).segmentId());
-        rulePopulator.populateExternalRules(vni, router, routerInterface);
+        rulePopulator.populateExternalRules(vni);
     }
 
     private Collection<OpenstackRouterInterface> getOpenstackRouterInterface(OpenstackRouter router) {
@@ -472,8 +470,7 @@
                 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
                 .filter(p -> p.deviceId().equals(router.id()))
                 .forEach(p -> {
-                    OpenstackRouterInterface routerInterface = portToRouterInterface(p);
-                    interfaces.add(routerInterface);
+                    interfaces.add(portToRouterInterface(p));
                 });
         return interfaces;
     }
@@ -529,9 +526,6 @@
             if (event.type().equals(NetworkConfigEvent.Type.CONFIG_ADDED) ||
                     event.type().equals(NetworkConfigEvent.Type.CONFIG_UPDATED)) {
                 l3EventExecutorService.execute(OpenstackRoutingManager.this::readConfiguration);
-                rulePopulator = new OpenstackRoutingRulePopulator(appId,
-                        openstackService, flowObjectiveService, deviceService, driverService, config);
-
             }
         }
     }
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java
index 30f439b..d8d56e6 100644
--- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java
+++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java
@@ -49,7 +49,6 @@
 import org.onosproject.net.packet.InboundPacket;
 import org.onosproject.openstackinterface.OpenstackInterfaceService;
 import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstackinterface.OpenstackRouter;
 import org.onosproject.openstackinterface.OpenstackRouterInterface;
 import org.onosproject.openstackinterface.OpenstackSubnet;
 import org.onosproject.openstackinterface.OpenstackFloatingIP;
@@ -82,11 +81,11 @@
     private static final String PORTNOTNULL = "Port can not be null";
     private static final String DEVICENOTNULL = "Device can not be null";
     private static final String TUNNEL_DESTINATION = "tunnelDst";
-    private static final String DEVICE_ANNOTATION_CHANNELID = "channelId";
     private static final int ROUTING_RULE_PRIORITY = 25000;
     private static final int FLOATING_RULE_PRIORITY = 42000;
     private static final int PNAT_RULE_PRIORITY = 26000;
     private static final int PNAT_TIMEOUT = 120;
+    private static final int PREFIX_LENGTH = 32;
     private static final MacAddress GATEWAYMAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
 
     private InboundPacket inboundPacket;
@@ -94,8 +93,6 @@
     private int portNum;
     private MacAddress externalInterface;
     private MacAddress externalRouter;
-    private OpenstackRouter router;
-    private OpenstackRouterInterface routerInterface;
 
     /**
      * The constructor of openstackRoutingRulePopulator.
@@ -247,7 +244,7 @@
 
     private Ip4Address getHostIpfromOpenstackPort(OpenstackPort openstackPort) {
         Device device = getDevicefromOpenstackPort(openstackPort);
-        return getIPAddressforDevice(device);
+        return config.nodes().get(device.id());
     }
 
     private Device getDevicefromOpenstackPort(OpenstackPort openstackPort) {
@@ -266,7 +263,7 @@
                 .filter(p -> p.isEnabled() && p.annotations().value(PORTNAME).equals(openstackPortName))
                 .findAny()
                 .orElse(null);
-        return port != null ? true : false;
+        return port != null;
     }
 
     /**
@@ -317,13 +314,8 @@
      * Populates flow rules from openstackComputeNode to GatewayNode.
      *
      * @param vni Target network
-     * @param router corresponding router
-     * @param routerInterface corresponding routerInterface
      */
-    public void populateExternalRules(long vni, OpenstackRouter router,
-                                      OpenstackRouterInterface routerInterface) {
-        this.router = router;
-        this.routerInterface = routerInterface;
+    public void populateExternalRules(long vni) {
 
         // 1. computeNode to gateway
         populateComputeNodeRules(vni);
@@ -367,7 +359,7 @@
         sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                 .matchTunnelId(vni)
                 .matchEthDst(GATEWAYMAC);
-        tBuilder.extension(buildNiciraExtenstion(d.id(), getIPAddressforDevice(gatewayDevice)), d.id())
+        tBuilder.extension(buildNiciraExtenstion(d.id(), config.nodes().get(gatewayDevice.id())), d.id())
                 .setOutput(getTunnelPort(d.id()));
 
         ForwardingObjective fo = DefaultForwardingObjective.builder()
@@ -381,10 +373,6 @@
         flowObjectiveService.forward(d.id(), fo);
     }
 
-    private Ip4Address getIPAddressforDevice(Device device) {
-        return Ip4Address.valueOf(device.annotations().value(DEVICE_ANNOTATION_CHANNELID).split(":")[0]);
-    }
-
     private Device getGatewayNode() {
         return checkNotNull(deviceService.getDevice(DeviceId.deviceId(config.gatewayBridgeId())));
     }
@@ -411,11 +399,10 @@
 
         StreamSupport.stream(deviceService.getDevices().spliterator(), false)
                 .forEach(d -> {
-                    if (checkGatewayNode(d.id())) {
-                        removeRule(d.id(), sBuilder, ForwardingObjective.Flag.VERSATILE, ROUTING_RULE_PRIORITY);
-                    } else {
-                        removeRule(d.id(), sBuilder, ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY);
-                    }
+                    ForwardingObjective.Flag flag = checkGatewayNode(d.id()) ?
+                            ForwardingObjective.Flag.VERSATILE : ForwardingObjective.Flag.SPECIFIC;
+
+                    removeRule(d.id(), sBuilder, flag, ROUTING_RULE_PRIORITY);
                 });
 
     }
@@ -457,13 +444,14 @@
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
 
         sBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), 32));
+                .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
 
         tBuilder.setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
                 .setEthDst(port.macAddress())
                 .setIpDst(floatingIP.fixedIpAddress())
                 .setTunnelId(getVni(port.networkId()))
-                .extension(buildNiciraExtenstion(gatewayNode.id(), getIPAddressforDevice(portNode)), gatewayNode.id())
+                .extension(buildNiciraExtenstion(gatewayNode.id(),
+                        config.nodes().get(portNode.id())), gatewayNode.id())
                 .setOutput(getTunnelPort(gatewayNode.id()));
 
         ForwardingObjective fo = DefaultForwardingObjective.builder()
@@ -516,10 +504,10 @@
 
         sOutgoingBuilder.matchEthType(Ethernet.TYPE_IPV4)
                 .matchTunnelId(portInfo.vni())
-                .matchIPSrc(IpPrefix.valueOf(portInfo.ip(), 32));
+                .matchIPSrc(IpPrefix.valueOf(portInfo.ip(), PREFIX_LENGTH));
 
         sIncomingBuilder.matchEthType(Ethernet.TYPE_IPV4)
-                .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), 32));
+                .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
 
         removeRule(getGatewayNode().id(), sOutgoingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);
         removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);