[ONOS-7863] Initial support GENEVE tunnel at SONA

Change-Id: Ia85d32e8068c22d59082dceccc0d911f8acb5f02
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
index d1236f1..18bad9b 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
@@ -120,6 +120,13 @@
     public static final int VTAP_FLAT_OUTBOUND_GROUP_TABLE = 2;
     public static final int VTAP_OUTBOUND_GROUP_TABLE = 3;
 
+    // network type
+    public static final String VXLAN = "VXLAN";
+    public static final String VLAN = "VLAN";
+    public static final String FLAT = "FLAT";
+    public static final String GRE = "GRE";
+    public static final String GENEVE = "GENEVE";
+
     public static Map<String, String> portNamePrefixMap() {
         return PORT_NAME_PREFIX_MAP;
     }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java
index 98bd413..e5301e5 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java
@@ -434,26 +434,31 @@
         Set<String> networkIds = Sets.newConcurrentHashSet();
 
         switch (type.toUpperCase()) {
-            case "FLAT" :
+            case Constants.FLAT :
                 networkIds = augmentedNetworkMap.asJavaMap().entrySet().stream()
                         .filter(e -> e.getValue().type() == FLAT)
                         .map(Map.Entry::getKey).collect(Collectors.toSet());
                 break;
-            case "VXLAN" :
+            case Constants.VXLAN :
                 networkIds = augmentedNetworkMap.asJavaMap().entrySet().stream()
-                        .filter(e -> e.getValue().type() == Type.VXLAN)
+                        .filter(e -> e.getValue().type() == VXLAN)
                         .map(Map.Entry::getKey).collect(Collectors.toSet());
                 break;
-            case "GRE" :
+            case Constants.GRE :
                 networkIds = augmentedNetworkMap.asJavaMap().entrySet().stream()
-                        .filter(e -> e.getValue().type() == Type.GRE)
+                        .filter(e -> e.getValue().type() == GRE)
                         .map(Map.Entry::getKey).collect(Collectors.toSet());
                 break;
-            case "VLAN" :
+            case Constants.VLAN :
                 networkIds = augmentedNetworkMap.asJavaMap().entrySet().stream()
                         .filter(e -> e.getValue().type() == VLAN)
                         .map(Map.Entry::getKey).collect(Collectors.toSet());
                 break;
+            case Constants.GENEVE :
+                networkIds = augmentedNetworkMap.asJavaMap().entrySet().stream()
+                        .filter(e -> e.getValue().type() == GENEVE)
+                        .map(Map.Entry::getKey).collect(Collectors.toSet());
+                break;
             default:
                 break;
         }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index 5a324ee..a9eef09 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -83,6 +83,7 @@
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GRE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VXLAN;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GENEVE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetworkEvent.Type.OPENSTACK_PORT_PRE_REMOVE;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.externalPeerRouterForNetwork;
@@ -341,9 +342,12 @@
             return;
         }
 
-        switch (osNet.getNetworkType()) {
+        Type netType = osNetworkService.networkType(osNet.getId());
+
+        switch (netType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
                         osNetworkService, osNodeService.node(instPort.deviceId()));
 
@@ -406,6 +410,11 @@
             final String error = String.format(errorFormat, floatingIp, cNode.hostname());
             throw new IllegalStateException(error);
         }
+        if (netType == GENEVE && cNode.dataIp() == null) {
+            final String errorFormat = ERR_FLOW + "GENEVE mode is not ready for %s";
+            final String error = String.format(errorFormat, floatingIp, cNode.hostname());
+            throw new IllegalStateException(error);
+        }
         if (netType == VLAN && cNode.vlanIntf() == null) {
             final String errorFormat = ERR_FLOW + "VLAN mode is not ready for %s";
             final String error = String.format(errorFormat, floatingIp, cNode.hostname());
@@ -436,9 +445,10 @@
             externalTreatmentBuilder.popVlan();
         }
 
-        switch (osNet.getNetworkType()) {
+        switch (netType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 PortNumber portNum = tunnelPortNumByNetId(instPort.networkId(),
                         osNetworkService, selectedGatewayNode);
                 externalTreatmentBuilder.setTunnelId(Long.valueOf(osNet.getProviderSegID()))
@@ -479,9 +489,12 @@
                 .matchEthType(Ethernet.TYPE_IPV4)
                 .matchIPSrc(instPort.ipAddress().toIpPrefix());
 
-        switch (osNet.getNetworkType()) {
+        Type netType = osNetworkService.networkType(osNet.getId());
+
+        switch (netType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 sBuilder.matchTunnelId(Long.valueOf(osNet.getProviderSegID()));
                 break;
             case VLAN:
@@ -494,7 +507,6 @@
         }
 
         TrafficSelector selector = sBuilder.build();
-        Type netType = osNetworkService.networkType(osNet.getId());
 
         osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
             TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
index bc02119..d1864d7 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
@@ -96,7 +96,10 @@
 import static org.onosproject.openstacknetworking.api.Constants.STAT_OUTBOUND_TABLE;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.FLAT;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GENEVE;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GRE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VXLAN;
 import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
 import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT_DEFAULT;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
@@ -460,21 +463,25 @@
 
         // take ICMP request to a subnet gateway through gateway node group
         Network net = osNetworkAdminService.network(osSubnet.getNetworkId());
+        Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
         Set<Subnet> routableSubnets = routableSubnets(osRouter, osSubnet.getId());
 
-        switch (net.getNetworkType()) {
+        switch (netType) {
             case VXLAN:
                 setGatewayIcmpForVxlan(osSubnet, srcNatGw, net, routableSubnets, install);
                 break;
             case GRE:
                 setGatewayIcmpForGre(osSubnet, srcNatGw, net, routableSubnets, install);
                 break;
+            case GENEVE:
+                setGatewayIcmpForGeneve(osSubnet, srcNatGw, net, routableSubnets, install);
+                break;
             case VLAN:
                 setGatewayIcmpForVlan(osSubnet, srcNatGw, net, routableSubnets, install);
                 break;
             default:
                 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
-                                                            net.getNetworkType().toString());
+                                                            netType.toString());
                 throw new IllegalStateException(error);
         }
 
@@ -502,7 +509,7 @@
                         network.getProviderSegID(),
                         osSubnet,
                         routableSubnets,
-                        Type.VXLAN,
+                        VXLAN,
                         install));
     }
 
@@ -519,7 +526,24 @@
                         network.getProviderSegID(),
                         osSubnet,
                         routableSubnets,
-                        Type.GRE,
+                        GRE,
+                        install));
+    }
+
+    private void setGatewayIcmpForGeneve(Subnet osSubnet,
+                                         OpenstackNode srcNatGw,
+                                         Network network,
+                                         Set<Subnet> routableSubnets,
+                                         boolean install) {
+        osNodeService.completeNodes(COMPUTE).stream()
+                .filter(cNode -> cNode.dataIp() != null)
+                .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
+                        cNode,
+                        srcNatGw,
+                        network.getProviderSegID(),
+                        osSubnet,
+                        routableSubnets,
+                        GENEVE,
                         install));
     }
 
@@ -629,6 +653,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 setInternalRouterRulesForTunnel(deviceId, srcSegId, dstSegId,
                                                 srcSubnet, dstSubnet, install);
                 break;
@@ -766,6 +791,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 sBuilder.matchTunnelId(Long.parseLong(segmentId));
                 break;
             case VLAN:
@@ -783,6 +809,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 PortNumber portNum = tunnelPortNumByNetType(networkType, osNode);
                 tBuilder.extension(buildExtension(
                                 deviceService,
@@ -883,6 +910,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 sBuilder.matchTunnelId(Long.parseLong(segmentId));
 
                 PortNumber portNum = tunnelPortNumByNetType(networkType, osNode);
@@ -994,6 +1022,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 sBuilder.matchTunnelId(Long.parseLong(segmentId));
                 break;
             case VLAN:
@@ -1034,6 +1063,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 sBuilder.matchTunnelId(Long.parseLong(segmentId));
                 break;
             case VLAN:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
index d1072cb..9ee5f3d 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
@@ -280,6 +280,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 tBuilder.setTunnelId(Long.parseLong(segmentId));
                 break;
             case VLAN:
@@ -334,6 +335,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 PortNumber portNum = tunnelPortNumByNetType(networkType, gNode);
                 tmpBuilder.extension(RulePopulatorUtil.buildExtension(
                         deviceService,
@@ -372,6 +374,7 @@
         switch (networkType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 sBuilder.matchTunnelId(Long.parseLong(segmentId));
                 break;
             case VLAN:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index 15920fe..140facf 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -107,6 +107,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_DROP_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_HOOK_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_CT_RULE;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GENEVE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GRE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VXLAN;
@@ -585,7 +586,7 @@
 
         if (netType == VLAN) {
             sBuilder.matchVlanId(VlanId.vlanId(segId));
-        } else if (netType == VXLAN || netType == GRE) {
+        } else if (netType == VXLAN || netType == GRE || netType == GENEVE) {
             sBuilder.matchTunnelId(Long.valueOf(segId));
         } else {
             log.warn("Cannot tag the VID due to lack of support of virtual network type {}", netType);
@@ -912,6 +913,7 @@
             switch (netType) {
                 case VXLAN:
                 case GRE:
+                case GENEVE:
                     sBuilder.matchTunnelId(Long.valueOf(segId));
                     break;
                 case VLAN:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
index 3ac0c0d..0e09b03 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
@@ -86,6 +86,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_REQUEST_RULE;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.FLAT;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GENEVE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GRE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VXLAN;
@@ -316,7 +317,7 @@
             if (netType == VLAN) {
                 sBuilder.matchVlanId(VlanId.vlanId(network.getProviderSegID()));
                 tBuilder.popVlan();
-            } else if (netType == VXLAN || netType == GRE) {
+            } else if (netType == VXLAN || netType == GRE || netType == GENEVE) {
                 // do not remove fake gateway ARP rules, if there is another gateway
                 // which has the same subnet that to be removed
                 // this only occurs if we have duplicated subnets associated with
@@ -381,6 +382,7 @@
         switch (netType) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 setRemoteArpRequestRuleForTunnel(port, install);
                 break;
             case VLAN:
@@ -407,6 +409,9 @@
             case GRE:
                 setArpReplyRuleForGre(port, install);
                 break;
+            case GENEVE:
+                setArpReplyRuleForGeneve(port, install);
+                break;
             case VLAN:
                 setArpReplyRuleForVlan(port, install);
                 break;
@@ -500,6 +505,22 @@
     }
 
     /**
+     * Installs flow rules to match ARP reply packets only for GENEVE.
+     *
+     * @param port      instance port
+     * @param install   installation flag
+     */
+    private void setArpReplyRuleForGeneve(InstancePort port, boolean install) {
+
+        OpenstackNode localNode = osNodeService.node(port.deviceId());
+
+        TrafficSelector selector = getArpReplySelectorForGeneve(port);
+
+        setLocalArpReplyTreatmentForGeneve(selector, port, install);
+        setRemoteArpTreatmentForTunnel(selector, port, localNode, install);
+    }
+
+    /**
      * Installs flow rules to match ARP reply packets only for VLAN.
      *
      * @param port      instance port
@@ -524,6 +545,11 @@
     }
 
     // a helper method
+    private TrafficSelector getArpReplySelectorForGeneve(InstancePort port) {
+        return getArpReplySelectorForVnet(port, GENEVE);
+    }
+
+    // a helper method
     private TrafficSelector getArpReplySelectorForVlan(InstancePort port) {
         return getArpReplySelectorForVnet(port, VLAN);
     }
@@ -562,6 +588,13 @@
     }
 
     // a helper method
+    private void setLocalArpReplyTreatmentForGeneve(TrafficSelector selector,
+                                                    InstancePort port,
+                                                    boolean install) {
+        setLocalArpReplyTreatmentForVnet(selector, port, GENEVE, install);
+    }
+
+    // a helper method
     private void setLocalArpReplyTreatmentForVlan(TrafficSelector selector,
                                                   InstancePort port,
                                                   boolean install) {
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 e4b22b5..0fab37e 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
@@ -500,6 +500,7 @@
         switch (type) {
             case VXLAN:
             case GRE:
+            case GENEVE:
                 setNetworkBlockRulesForTunnel(network.getProviderSegID(), install);
                 break;
             case VLAN:
@@ -734,7 +735,7 @@
 
         /**
          * Configures L2 forwarding rules.
-         * Currently, SONA supports Flat, VXLAN, GRE and VLAN modes.
+         * Currently, SONA supports Flat, VXLAN, GRE, GENEVE and VLAN modes.
          *
          * @param instPort instance port object
          * @param install install flag, add the rule if true, remove it otherwise
@@ -745,6 +746,7 @@
             switch (type) {
                 case VXLAN:
                 case GRE:
+                case GENEVE:
                     setNetworkRulesForTunnel(instPort, install);
                     break;
                 case VLAN:
@@ -794,6 +796,7 @@
             switch (type) {
                 case VXLAN:
                 case GRE:
+                case GENEVE:
                     removeVportRulesForTunnel(instPort);
                     break;
                 case VLAN:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index c4e3803..ce12d77 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -156,9 +156,6 @@
 
     private static final String ERR_FLOW = "Failed set flows for floating IP %s: ";
 
-    private static final String VXLAN = "VXLAN";
-    private static final String GRE = "GRE";
-    private static final String VLAN = "VLAN";
     private static final String DL_DST = "dl_dst=";
     private static final String NW_DST = "nw_dst=";
     private static final String DEFAULT_REQUEST_STRING = "sudo ovs-appctl ofproto/trace br-int ip";
@@ -770,9 +767,9 @@
                     .append(COMMA);
 
             String modifiedDstIp = dstIp;
-            if (osNetService.networkType(srcInstancePort.networkId()) == Type.VXLAN ||
-                    osNetService.networkType(srcInstancePort.networkId()) == Type.GRE ||
-                    osNetService.networkType(srcInstancePort.networkId()) == Type.VLAN) {
+            Type netType = osNetService.networkType(srcInstancePort.networkId());
+            if (netType == Type.VXLAN || netType == Type.GRE ||
+                    netType == Type.VLAN || netType == Type.GENEVE) {
                 if (srcIp.equals(dstIp)) {
                     modifiedDstIp = osNetService.gatewayIp(srcInstancePort.portId());
                     requestStringBuilder.append(DL_DST)
@@ -798,9 +795,10 @@
                     .append(dstIp)
                     .append(COMMA);
 
-            if (osNetService.networkType(srcInstancePort.networkId()) == Type.VXLAN ||
-                    osNetService.networkType(srcInstancePort.networkId()) == Type.GRE ||
-                    osNetService.networkType(srcInstancePort.networkId()) == Type.VLAN) {
+            Type netType = osNetService.networkType(srcInstancePort.networkId());
+
+            if (netType == Type.VXLAN || netType == Type.GRE ||
+                    netType == Type.VLAN || netType == Type.GENEVE) {
                 requestStringBuilder.append(TUN_ID)
                         .append(osNetService.segmentId(srcInstancePort.networkId()))
                         .append(COMMA);
@@ -1083,6 +1081,8 @@
                 return osNode.vxlanTunnelPortNum();
             case GRE:
                 return osNode.greTunnelPortNum();
+            case GENEVE:
+                return osNode.geneveTunnelPortNum();
             default:
                 return null;
         }
diff --git a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java
index 3c96590..bfb18c8 100644
--- a/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java
+++ b/apps/openstacknetworkingui/src/main/java/org/onosproject/openstacknetworkingui/OpenstackNetworkingUiMessageHandler.java
@@ -43,7 +43,7 @@
 import org.onosproject.net.topology.PathService;
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.InstancePortService;
-import org.onosproject.openstacknetworking.api.OpenstackNetwork;
+import org.onosproject.openstacknetworking.api.OpenstackNetwork.Type;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeService;
@@ -75,6 +75,7 @@
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
 import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
+import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GENEVE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GRE;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
 import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VXLAN;
@@ -505,9 +506,9 @@
                     .append(srcIp)
                     .append(COMMA);
 
-            OpenstackNetwork.Type netType = osNetService.networkType(srcInstancePort.networkId());
+            Type netType = osNetService.networkType(srcInstancePort.networkId());
 
-            if (netType == VXLAN || netType == VLAN || netType == GRE) {
+            if (netType == VXLAN || netType == VLAN || netType == GRE || netType == GENEVE) {
                 if (srcIp.equals(dstIp)) {
                     dstIp = osNetService.gatewayIp(srcInstancePort.portId());
                     requestStringBuilder.append(DL_DST)
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 e78d0e6..8decf3a 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
@@ -28,6 +28,7 @@
     public static final String ROUTER_BRIDGE = "br-router";
     public static final String VXLAN_TUNNEL = "vxlan";
     public static final String GRE_TUNNEL = "gre";
+    public static final String GENEVE_TUNNEL = "geneve";
     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 1ea5942..5d79f7d 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,6 +35,7 @@
 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.GENEVE_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;
@@ -193,6 +194,11 @@
     }
 
     @Override
+    public PortNumber geneveTunnelPortNum() {
+        return tunnelPortNum(GENEVE_TUNNEL);
+    }
+
+    @Override
     public PortNumber greTunnelPortNum() {
         return tunnelPortNum(GRE_TUNNEL);
 
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 63f8ef2..2578eb8 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
@@ -109,6 +109,13 @@
     PortNumber vxlanTunnelPortNum();
 
     /**
+     * Returns the GENEVE tunnel port number.
+     *
+     * @return GENEVE port number; null if the GRE tunnel port does not exist
+     */
+    PortNumber geneveTunnelPortNum();
+
+    /**
      * Returns the vlan port number.
      *
      * @return port number; null if vlan port does not exist
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 451139e..79a2048 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
@@ -79,6 +79,11 @@
     }
 
     @Override
+    public PortNumber geneveTunnelPortNum() {
+        return null;
+    }
+
+    @Override
     public PortNumber vlanPortNum() {
         return null;
     }
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 1b93499..c2c3d57 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
@@ -79,6 +79,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.GENEVE;
+import static org.onosproject.openstacknode.api.Constants.GENEVE_TUNNEL;
 import static org.onosproject.openstacknode.api.Constants.GRE;
 import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
 import static org.onosproject.openstacknode.api.Constants.INTEGRATION_BRIDGE;
@@ -235,6 +237,11 @@
                 createGreTunnelInterface(osNode);
             }
 
+            if (osNode.dataIp() != null &&
+                    !isIntfEnabled(osNode, GENEVE_TUNNEL)) {
+                createGeneveTunnelInterface(osNode);
+            }
+
             if (osNode.dpdkConfig() != null && osNode.dpdkConfig().dpdkIntfs() != null) {
                 osNode.dpdkConfig().dpdkIntfs().stream()
                         .filter(dpdkintf -> dpdkintf.deviceName().equals(TUNNEL_BRIDGE))
@@ -260,7 +267,7 @@
                             osNode.vlanIntf(), deviceService, true);
             }
         } catch (Exception e) {
-            log.error("Exception occurred because of {}", e.toString());
+            log.error("Exception occurred because of {}", e);
         }
     }
 
@@ -365,6 +372,15 @@
     }
 
     /**
+     * Creates a GENEVE tunnel interface in a given openstack node.
+     *
+     * @param osNode openstack node
+     */
+    private void createGeneveTunnelInterface(OpenstackNode osNode) {
+        createTunnelInterface(osNode, GENEVE, GENEVE_TUNNEL);
+    }
+
+    /**
      * Creates a tunnel interface in a given openstack node.
      *
      * @param osNode openstack node
@@ -394,7 +410,7 @@
      * @return tunnel description
      */
     private TunnelDescription buildTunnelDesc(String type, String intfName) {
-        if (VXLAN.equals(type) || GRE.equals(type)) {
+        if (VXLAN.equals(type) || GRE.equals(type) || GENEVE.equals(type)) {
             TunnelDescription.Builder tdBuilder =
                     DefaultTunnelDescription.builder()
                     .deviceId(INTEGRATION_BRIDGE)
@@ -409,6 +425,9 @@
                 case GRE:
                     tdBuilder.type(TunnelDescription.Type.GRE);
                     break;
+                case GENEVE:
+                    tdBuilder.type(TunnelDescription.Type.GENEVE);
+                    break;
                 default:
                     return null;
             }
@@ -462,6 +481,10 @@
                         !isIntfEnabled(osNode, GRE_TUNNEL)) {
                     return false;
                 }
+                if (osNode.dataIp() != null &&
+                        !isIntfEnabled(osNode, GENEVE_TUNNEL)) {
+                    return false;
+                }
                 if (osNode.vlanIntf() != null &&
                         !isIntfEnabled(osNode, osNode.vlanIntf())) {
                     return false;
@@ -819,6 +842,7 @@
                         if (osNode.state() == DEVICE_CREATED && (
                                 Objects.equals(portName, VXLAN_TUNNEL) ||
                                 Objects.equals(portName, GRE_TUNNEL) ||
+                                Objects.equals(portName, GENEVE_TUNNEL) ||
                                 Objects.equals(portName, osNode.vlanIntf()) ||
                                 Objects.equals(portName, osNode.uplinkPort()) ||
                                         containsPhyIntf(osNode, portName)) ||
@@ -847,6 +871,7 @@
                         if (osNode.state() == COMPLETE && (
                                 Objects.equals(portName, VXLAN_TUNNEL) ||
                                 Objects.equals(portName, GRE_TUNNEL) ||
+                                Objects.equals(portName, GENEVE_TUNNEL) ||
                                 Objects.equals(portName, osNode.vlanIntf()) ||
                                 Objects.equals(portName, osNode.uplinkPort()) ||
                                         containsPhyIntf(osNode, portName)) ||