Initial support GRE tunnel at SONA

Change-Id: I86536a3ed23d8df45e1dc4033c3068a4dfc9ec73
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/Constants.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/Constants.java
index b7ca1f5..0422c65 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/Constants.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/Constants.java
@@ -26,7 +26,8 @@
     public static final String INTEGRATION_BRIDGE = "br-int";
     public static final String TUNNEL_BRIDGE = "br-tun";
     public static final String ROUTER_BRIDGE = "br-router";
-    public static final String DEFAULT_TUNNEL = "vxlan";
+    public static final String VXLAN_TUNNEL = "vxlan";
+    public static final String GRE_TUNNEL = "gre";
     public static final String PATCH_INTG_BRIDGE = "patch-intg";
     public static final String PATCH_ROUT_BRIDGE = "patch-rout";
     public static final String GATEWAY = "GATEWAY";
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
index ca4734e..1ea5942 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
@@ -35,7 +35,8 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.onosproject.net.AnnotationKeys.PORT_MAC;
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
-import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
 import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
 
 /**
@@ -185,15 +186,26 @@
         return port != null ? port.number() : null;
 
     }
+
     @Override
-    public PortNumber tunnelPortNum() {
+    public PortNumber vxlanTunnelPortNum() {
+        return tunnelPortNum(VXLAN_TUNNEL);
+    }
+
+    @Override
+    public PortNumber greTunnelPortNum() {
+        return tunnelPortNum(GRE_TUNNEL);
+
+    }
+
+    private PortNumber tunnelPortNum(String tunnelType) {
         if (dataIp == null) {
             return null;
         }
         DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
         Port port = deviceService.getPorts(intgBridge).stream()
                 .filter(p -> p.isEnabled() &&
-                        Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
+                        Objects.equals(p.annotations().value(PORT_NAME), tunnelType))
                 .findAny().orElse(null);
         return port != null ? port.number() : null;
     }
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
index a2000ee..63f8ef2 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
@@ -30,16 +30,6 @@
 public interface OpenstackNode {
 
     /**
-     * List of valid network modes.
-     * This includes both physical and virtual network types.
-     */
-    enum NetworkMode {
-        VXLAN,
-        VLAN,
-        FLAT
-    }
-
-    /**
      * List of valid node types.
      */
     enum NodeType {
@@ -105,11 +95,18 @@
     NodeState state();
 
     /**
-     * Returns the tunnel port number.
+     * Returns the GRE tunnel port number.
      *
-     * @return port number; null if tunnel port does not exist
+     * @return GRE port number; null if the GRE tunnel port does not exist
      */
-    PortNumber tunnelPortNum();
+    PortNumber greTunnelPortNum();
+
+    /**
+     * Returns the VXLAN tunnel port number.
+     *
+     * @return VXLAN port number; null if tunnel port does not exist
+     */
+    PortNumber vxlanTunnelPortNum();
 
     /**
      * Returns the vlan port number.
diff --git a/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java b/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
index d625a05..451139e 100644
--- a/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
+++ b/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
@@ -69,7 +69,12 @@
     }
 
     @Override
-    public PortNumber tunnelPortNum() {
+    public PortNumber greTunnelPortNum() {
+        return null;
+    }
+
+    @Override
+    public PortNumber vxlanTunnelPortNum() {
         return null;
     }
 
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
index 88321c3..1ff9169 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeCheckCommand.java
@@ -31,7 +31,8 @@
 import org.openstack4j.api.OSClient;
 
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
-import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
 import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
@@ -93,7 +94,8 @@
                         deviceService.isAvailable(device.id()),
                         device.annotations());
                 if (osNode.dataIp() != null) {
-                    printPortState(deviceService, osNode.intgBridge(), DEFAULT_TUNNEL);
+                    printPortState(deviceService, osNode.intgBridge(), VXLAN_TUNNEL);
+                    printPortState(deviceService, osNode.intgBridge(), GRE_TUNNEL);
                 }
                 if (osNode.vlanIntf() != null) {
                     printPortState(deviceService, osNode.intgBridge(), osNode.vlanIntf());
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
index aaf48fa..c6e9395 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
@@ -57,6 +57,7 @@
 import org.onosproject.ovsdb.rfc.notation.OvsdbSet;
 import org.onosproject.ovsdb.rfc.table.Interface;
 import org.openstack4j.api.OSClient;
+import org.openstack4j.model.network.NetworkType;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -79,7 +80,8 @@
 import static org.onlab.packet.TpPort.tpPort;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
-import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
 import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
 import static org.onosproject.openstacknode.api.Constants.TUNNEL_BRIDGE;
 import static org.onosproject.openstacknode.api.DpdkConfig.DatapathType.NETDEV;
@@ -223,8 +225,13 @@
             }
 
             if (osNode.dataIp() != null &&
-                    !isIntfEnabled(osNode, DEFAULT_TUNNEL)) {
-                createTunnelInterface(osNode);
+                    !isIntfEnabled(osNode, VXLAN_TUNNEL)) {
+                createVxlanTunnelInterface(osNode);
+            }
+
+            if (osNode.dataIp() != null &&
+                    !isIntfEnabled(osNode, GRE_TUNNEL)) {
+                createGreTunnelInterface(osNode);
             }
 
             if (osNode.dpdkConfig() != null && osNode.dpdkConfig().dpdkIntfs() != null) {
@@ -339,12 +346,31 @@
     }
 
     /**
+     * Creates a VXLAN tunnel interface in a given openstack node.
+     *
+     * @param osNode openstack node
+     */
+    private void createVxlanTunnelInterface(OpenstackNode osNode) {
+        createTunnelInterface(osNode, NetworkType.VXLAN, VXLAN_TUNNEL);
+    }
+
+    /**
+     * Creates a GRE tunnel interface in a given openstack node.
+     *
+     * @param osNode openstack node
+     */
+    private void createGreTunnelInterface(OpenstackNode osNode) {
+        createTunnelInterface(osNode, NetworkType.GRE, GRE_TUNNEL);
+    }
+
+    /**
      * Creates a tunnel interface in a given openstack node.
      *
      * @param osNode openstack node
      */
-    private void createTunnelInterface(OpenstackNode osNode) {
-        if (isIntfEnabled(osNode, DEFAULT_TUNNEL)) {
+    private void createTunnelInterface(OpenstackNode osNode,
+                                       NetworkType type, String intfName) {
+        if (isIntfEnabled(osNode, intfName)) {
             return;
         }
 
@@ -354,16 +380,41 @@
             return;
         }
 
-        TunnelDescription tunnelDesc = DefaultTunnelDescription.builder()
-                .deviceId(INTEGRATION_BRIDGE)
-                .ifaceName(DEFAULT_TUNNEL)
-                .type(TunnelDescription.Type.VXLAN)
-                .remote(TunnelEndPoints.flowTunnelEndpoint())
-                .key(TunnelKeys.flowTunnelKey())
-                .build();
+        TunnelDescription tunnelDesc = buildTunnelDesc(type, intfName);
 
         InterfaceConfig ifaceConfig = device.as(InterfaceConfig.class);
-        ifaceConfig.addTunnelMode(DEFAULT_TUNNEL, tunnelDesc);
+        ifaceConfig.addTunnelMode(intfName, tunnelDesc);
+    }
+
+    /**
+     * Builds tunnel description according to the network type.
+     *
+     * @param type network type
+     * @return tunnel description
+     */
+    private TunnelDescription buildTunnelDesc(NetworkType type, String intfName) {
+        if (type ==  NetworkType.VXLAN || type == NetworkType.GRE) {
+            TunnelDescription.Builder tdBuilder =
+                    DefaultTunnelDescription.builder()
+                    .deviceId(INTEGRATION_BRIDGE)
+                    .ifaceName(intfName)
+                    .remote(TunnelEndPoints.flowTunnelEndpoint())
+                    .key(TunnelKeys.flowTunnelKey());
+
+            switch (type) {
+                case VXLAN:
+                    tdBuilder.type(TunnelDescription.Type.VXLAN);
+                    break;
+                case GRE:
+                    tdBuilder.type(TunnelDescription.Type.GRE);
+                    break;
+                default:
+                    return null;
+            }
+
+            return tdBuilder.build();
+        }
+        return null;
     }
 
     /**
@@ -403,7 +454,11 @@
                 return initStateDone;
             case DEVICE_CREATED:
                 if (osNode.dataIp() != null &&
-                        !isIntfEnabled(osNode, DEFAULT_TUNNEL)) {
+                        !isIntfEnabled(osNode, VXLAN_TUNNEL)) {
+                    return false;
+                }
+                if (osNode.dataIp() != null &&
+                        !isIntfEnabled(osNode, GRE_TUNNEL)) {
                     return false;
                 }
                 if (osNode.vlanIntf() != null &&
@@ -761,7 +816,8 @@
                         Port port = event.port();
                         String portName = port.annotations().value(PORT_NAME);
                         if (osNode.state() == DEVICE_CREATED && (
-                                Objects.equals(portName, DEFAULT_TUNNEL) ||
+                                Objects.equals(portName, VXLAN_TUNNEL) ||
+                                Objects.equals(portName, GRE_TUNNEL) ||
                                 Objects.equals(portName, osNode.vlanIntf()) ||
                                 Objects.equals(portName, osNode.uplinkPort()) ||
                                         containsPhyIntf(osNode, portName)) ||
@@ -788,7 +844,8 @@
                         Port port = event.port();
                         String portName = port.annotations().value(PORT_NAME);
                         if (osNode.state() == COMPLETE && (
-                                Objects.equals(portName, DEFAULT_TUNNEL) ||
+                                Objects.equals(portName, VXLAN_TUNNEL) ||
+                                Objects.equals(portName, GRE_TUNNEL) ||
                                 Objects.equals(portName, osNode.vlanIntf()) ||
                                 Objects.equals(portName, osNode.uplinkPort()) ||
                                         containsPhyIntf(osNode, portName)) ||
diff --git a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java
index ad5ab65..3224a4b 100644
--- a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java
+++ b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandlerTest.java
@@ -99,7 +99,7 @@
 import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
 import static org.onosproject.net.device.DeviceEvent.Type.PORT_ADDED;
 import static org.onosproject.net.device.DeviceEvent.Type.PORT_REMOVED;
-import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
 import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
 import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
 import static org.onosproject.openstacknode.api.Constants.PATCH_ROUT_BRIDGE;
@@ -369,7 +369,7 @@
         assertEquals(ERR_STATE_NOT_MATCH, COMPLETE,
                 testNodeManager.node(COMPUTE_3_HOSTNAME).state());
         TEST_DEVICE_SERVICE.removePort(COMPUTE_3_INTG_DEVICE, createPort(
-                COMPUTE_3_INTG_DEVICE, DEFAULT_TUNNEL));
+                COMPUTE_3_INTG_DEVICE, VXLAN_TUNNEL));
         assertEquals(ERR_STATE_NOT_MATCH, INCOMPLETE,
                 testNodeManager.node(COMPUTE_3_HOSTNAME).state());
 
@@ -523,7 +523,7 @@
         }
 
         @Override
-        public PortNumber tunnelPortNum() {
+        public PortNumber vxlanTunnelPortNum() {
             return PortNumber.portNumber(1);
         }