[Falcon] SONA : Supports routers

Adds the flow rules for router to the network node and compute nodes when a router is added.

Change-Id: I6e159b813a32f8e8b48f488d66731f882cf867ed
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
index 564ae99..be1a9eb 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
@@ -31,6 +31,7 @@
 import org.onosproject.dhcp.DhcpService;
 import org.onosproject.event.AbstractEvent;
 import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
 import org.onosproject.net.Port;
 import org.onosproject.net.config.ConfigFactory;
@@ -98,6 +99,11 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DriverService driverService;
 
+    public static final String PORTNAME_PREFIX_VM = "tap";
+    public static final String PORTNAME_PREFIX_ROUTER = "qr";
+    public static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
+    public static final String PORTNAME = "portName";
+
     private ApplicationId appId;
     private boolean doNotPushFlows;
     private Ip4Address neutronServer;
@@ -195,7 +201,7 @@
     @Override
     public OpenstackPort port(Port port) {
         Collection<OpenstackPort> ports = restHandler.getPorts();
-        String uuid = port.annotations().value("portName").substring(3);
+        String uuid = port.annotations().value(PORTNAME).substring(3);
         return ports.stream()
                 .filter(p -> p.id().startsWith(uuid))
                 .findFirst().orElse(null);
@@ -253,37 +259,23 @@
     }
 
     private void processPortUpdated(Device device, Port port) {
-        if (!port.annotations().value("portName").equals("vxlan") && !doNotPushFlows) {
-            if (port.isEnabled()) {
+        if (!port.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL) && !doNotPushFlows) {
+            if (port.isEnabled() || port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER)) {
                 OpenstackSwitchingRulePopulator rulePopulator =
                         new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                                 deviceService, restHandler, driverService);
                 rulePopulator.populateSwitchingRules(device, port);
+                updatePortMap(device.id(), port, restHandler.getNetworks(), rulePopulator.openstackPort(port));
 
-                OpenstackPort openstackPort = port(port);
-
-                long vni = Long.parseLong(restHandler.getNetworks().stream()
-                        .filter(n -> n.id().equals(openstackPort.networkId()))
-                        .findAny().orElse(null).segmentId());
-
-                OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
-                        .setDeviceId(device.id())
-                        .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
-                        .setVNI(vni);
-
-                openstackPortInfoMap.putIfAbsent(port.annotations().value("portName"),
-                        portBuilder.build());
-            }
-
-            //In case portupdate event is driven by vm shutoff from openstack
-            if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value("portName"))) {
+                //In case portupdate event is driven by vm shutoff from openstack
+            } else if (!port.isEnabled() && openstackPortInfoMap.containsKey(port.annotations().value(PORTNAME))) {
                 log.debug("Flowrules according to the port {} were removed", port.number().toString());
                 OpenstackSwitchingRulePopulator rulePopulator =
                         new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                                 deviceService, restHandler, driverService);
-                openstackPortInfoMap.get(port.annotations().value("portName"));
+                openstackPortInfoMap.get(port.annotations().value(PORTNAME));
                 rulePopulator.removeSwitchingRules(port, openstackPortInfoMap);
-                openstackPortInfoMap.remove(port.annotations().value("portName"));
+                openstackPortInfoMap.remove(port.annotations().value(PORTNAME));
             }
         }
     }
@@ -297,16 +289,20 @@
                 new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
                         deviceService, restHandler, driverService);
 
+        Collection<OpenstackNetwork> networks = restHandler.getNetworks();
+
         deviceService.getDevices().forEach(device -> {
                     log.debug("device {} num of ports {} ", device.id(),
                             deviceService.getPorts(device.id()).size());
                     deviceService.getPorts(device.id()).stream()
-                            .filter(port -> port.annotations().value("portName").startsWith("tap"))
+                            .filter(port -> port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_VM) ||
+                                    port.annotations().value(PORTNAME).startsWith(PORTNAME_PREFIX_ROUTER))
                             .forEach(vmPort -> {
                                         OpenstackPort osPort = rulePopulator.openstackPort(vmPort);
                                         if (osPort != null) {
                                             if (!doNotPushFlows) {
                                                 rulePopulator.populateSwitchingRules(device, vmPort);
+                                                updatePortMap(device.id(), vmPort, networks, osPort);
                                             }
                                             registerDhcpInfo(osPort);
                                         } else {
@@ -318,6 +314,21 @@
         );
     }
 
+    private void updatePortMap(DeviceId deviceId, Port port, Collection<OpenstackNetwork> networks,
+                               OpenstackPort openstackPort) {
+        long vni = Long.parseLong(networks.stream()
+                .filter(n -> n.id().equals(openstackPort.networkId()))
+                .findAny().orElse(null).segmentId());
+
+        OpenstackPortInfo.Builder portBuilder = OpenstackPortInfo.builder()
+                .setDeviceId(deviceId)
+                .setHostIp((Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null))
+                .setVNI(vni);
+
+        openstackPortInfoMap.putIfAbsent(port.annotations().value(PORTNAME),
+                portBuilder.build());
+    }
+
     private void processHostRemoved(Host host) {
         log.debug("host {} was removed", host.toString());
     }
@@ -325,8 +336,8 @@
     private void registerDhcpInfo(OpenstackPort openstackPort) {
         Ip4Address ip4Address;
         Ip4Address subnetMask;
-        Ip4Address dhcpServer;
         Ip4Address gatewayIPAddress;
+        Ip4Address dhcpServer;
         Ip4Address domainServer;
         OpenstackSubnet openstackSubnet;
 
@@ -480,6 +491,5 @@
                networkEventExcutorService.execute(this::configureNetwork);
             }
         }
-
     }
 }
\ No newline at end of file
diff --git a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
index f5f93dc..014eeb8 100644
--- a/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
+++ b/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
@@ -208,7 +208,9 @@
                         String cidx = d.annotations().value("channelId");
                         Ip4Address hostIpx = Ip4Address.valueOf(cidx.split(":")[0]);
                         Ip4Address fixedIpx = getFixedIpAddressForPort(pName);
-                        if (port.isEnabled()) {
+                        if (port.isEnabled() ||
+                                port.annotations().value("portName").startsWith(
+                                        OpenstackSwitchingManager.PORTNAME_PREFIX_ROUTER)) {
                             setVxLanFlowRule(vni, device.id(), hostIpx, fixedIpx);
                             setVxLanFlowRule(vni, d.id(), hostIpAddress, fixedIp);
                         }
@@ -475,7 +477,8 @@
 
     private PortNumber getTunnelPort(DeviceId deviceId) {
         Port port = deviceService.getPorts(deviceId).stream()
-                .filter(p -> p.annotations().value("portName").equals("vxlan"))
+                .filter(p -> p.annotations().value("portName").equals(
+                        OpenstackSwitchingManager.PORTNAME_PREFIX_TUNNEL))
                 .findAny().orElse(null);
 
         if (port == null) {