[ONOS-4702] Fixed Openstack ARP/ICMP in OpenstackNetworkingService.

-Fixes ICMP/ARP handler to deals with floatingIP.
-Fixed some bugs in ARP/ICMP handler.

Change-Id: Ie06fdcce25f8a58e2f14e9050bfb7e430ddfd3af
diff --git a/apps/openstackinterface/api/src/main/java/org/onosproject/openstackinterface/OpenstackSecurityGroupRule.java b/apps/openstackinterface/api/src/main/java/org/onosproject/openstackinterface/OpenstackSecurityGroupRule.java
index 5934e3b..15fdcd9 100644
--- a/apps/openstackinterface/api/src/main/java/org/onosproject/openstackinterface/OpenstackSecurityGroupRule.java
+++ b/apps/openstackinterface/api/src/main/java/org/onosproject/openstackinterface/OpenstackSecurityGroupRule.java
@@ -347,7 +347,7 @@
         public OpenstackSecurityGroupRule build() {
 
             int portRangeMinInt = (portRangeMin == null || portRangeMin.equals("null")) ?
-                    -1 : Integer.parseInt(portRangeMax);
+                    -1 : Integer.parseInt(portRangeMin);
             int portRangeMaxInt = (portRangeMax == null || portRangeMax.equals("null")) ?
                     -1 : Integer.parseInt(portRangeMax);
             IpPrefix ipPrefix = (remoteIpPrefix == null || remoteIpPrefix.equals("null")) ?
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java
index 4c5dc38..71fb81c 100644
--- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java
+++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackIcmpHandler.java
@@ -66,14 +66,16 @@
     private static final MacAddress GATEWAY_MAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
     private static final String NETWORK_ROUTER_INTERFACE = "network:router_interface";
     private static final String PORTNAME = "portName";
+    private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
+    private static final String NETWORK_FLOATING_IP = "network:floatingip";
 
     /**
      * Default constructor.
      *
-     * @param packetService packet service
-     * @param deviceService device service
-     * @param openstackService openstackInterface service
-     * @param config openstackRoutingConfig
+     * @param packetService             packet service
+     * @param deviceService             device service
+     * @param openstackService          openstackInterface service
+     * @param config                    openstackRoutingConfig
      * @param openstackSwitchingService openstackSwitching service
      */
     OpenstackIcmpHandler(PacketService packetService, DeviceService deviceService,
@@ -106,7 +108,7 @@
     /**
      * Handles ICMP packet.
      *
-     * @param context packet context
+     * @param context  packet context
      * @param ethernet ethernet
      */
     public void processIcmpPacket(PacketContext context, Ethernet ethernet) {
@@ -122,13 +124,30 @@
         short icmpId = getIcmpId(icmp);
 
         DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
+        PortNumber portNumber = context.inPacket().receivedFrom().port();
         if (icmp.getIcmpType() == ICMP.TYPE_ECHO_REQUEST) {
             //TODO: Considers icmp between internal subnets which are belonged to the same router.
 
             OpenstackPortInfo openstackPortInfo =
                     getOpenstackPortInfo(Ip4Address.valueOf(ipPacket.getSourceAddress()), ethernet.getSourceMAC());
 
-            checkNotNull(openstackPortInfo, "openstackPortInfo can not be null");
+            //checkNotNull(openstackPortInfo, "openstackPortInfo can not be null");
+            if (requestToOpenstackRoutingNetwork(ipPacket.getDestinationAddress())) {
+                if (openstackPortInfo == null) {
+                    if (config.gatewayBridgeId().equals(context.inPacket().receivedFrom().deviceId().toString())) {
+                         if (portNumber.equals(getPortForAnnotationPortName(deviceId,
+                                        config.gatewayExternalInterfaceName()))) {
+                            processIcmpPacketSentToExtenal(ipPacket, icmp, ipPacket.getSourceAddress(),
+                                    ethernet.getSourceMAC(), deviceId, portNumber);
+                            return;
+                        }
+                    }
+                    return;
+                } else {
+                    processIcmpPacketSentToGateway(ipPacket, icmp, openstackPortInfo);
+                    return;
+                }
+            }
 
             if (ipPacket.getDestinationAddress() == openstackPortInfo.gatewayIP().toInt()) {
                 processIcmpPacketSentToGateway(ipPacket, icmp, openstackPortInfo);
@@ -154,8 +173,27 @@
         }
     }
 
+    private void processIcmpPacketSentToExtenal(IPv4 icmpRequestIpv4, ICMP icmpRequest,
+                                                int destAddr, MacAddress destMac,
+                                                DeviceId deviceId, PortNumber portNumber) {
+        icmpRequest.setChecksum((short) 0);
+        icmpRequest.setIcmpType(ICMP.TYPE_ECHO_REPLY).resetChecksum();
+        icmpRequestIpv4.setSourceAddress(icmpRequestIpv4.getDestinationAddress())
+                .setDestinationAddress(destAddr).resetChecksum();
+        icmpRequestIpv4.setPayload(icmpRequest);
+        Ethernet icmpResponseEth = new Ethernet();
+        icmpResponseEth.setEtherType(Ethernet.TYPE_IPV4)
+                .setSourceMACAddress(config.gatewayExternalInterfaceMac())
+                .setDestinationMACAddress(destMac).setPayload(icmpRequestIpv4);
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(portNumber).build();
+        OutboundPacket packet = new DefaultOutboundPacket(deviceId,
+                treatment, ByteBuffer.wrap(icmpResponseEth.serialize()));
+        packetService.emit(packet);
+    }
+
     private void processIcmpPacketSentToGateway(IPv4 icmpRequestIpv4, ICMP icmpRequest,
                                                 OpenstackPortInfo openstackPortInfo) {
+        icmpRequest.setChecksum((short) 0);
         icmpRequest.setIcmpType(ICMP.TYPE_ECHO_REPLY)
                 .resetChecksum();
 
@@ -272,4 +310,17 @@
 
         return port.number();
     }
-}
+
+    private boolean requestToOpenstackRoutingNetwork(int destAddr) {
+        OpenstackPort port = openstackService.ports().stream()
+                .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
+                        p.deviceOwner().equals(NETWORK_FLOATING_IP))
+                .filter(p -> p.fixedIps().containsValue(
+                        Ip4Address.valueOf(destAddr)))
+                .findAny().orElse(null);
+        if (port == null) {
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java
index 7dee2c1..0ad2101 100644
--- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingArpHandler.java
@@ -52,6 +52,7 @@
     private final OpenstackInterfaceService openstackService;
     private final OpenstackNetworkingConfig config;
     private static final String NETWORK_ROUTER_GATEWAY = "network:router_gateway";
+    private static final String NETWORK_FLOATING_IP = "network:floatingip";
 
     /**
      * Default constructor.
@@ -106,11 +107,11 @@
         }
 
         IpAddress targetIp = Ip4Address.valueOf(arp.getTargetProtocolAddress());
-        MacAddress targetMac = getTargetMacForTargetIp(targetIp.getIp4Address());
 
-        if (targetMac == MacAddress.NONE) {
-            return;
+        if (getTargetMacForTargetIp(targetIp.getIp4Address()) == MacAddress.NONE) {
+                return;
         }
+        MacAddress targetMac = MacAddress.valueOf(config.gatewayExternalInterfaceMac());
 
         Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
                 targetMac, ethernet);
@@ -127,7 +128,8 @@
 
     private MacAddress getTargetMacForTargetIp(Ip4Address targetIp) {
         OpenstackPort port = openstackService.ports().stream()
-                .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY))
+                .filter(p -> p.deviceOwner().equals(NETWORK_ROUTER_GATEWAY) ||
+                             p.deviceOwner().equals(NETWORK_FLOATING_IP))
                 .filter(p -> p.fixedIps().containsValue(targetIp.getIp4Address()))
                 .findAny().orElse(null);
 
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 2207ff6..88bc2ce 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
@@ -451,7 +451,7 @@
         sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                 .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
 
-        tBuilder.setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
+        tBuilder.setEthSrc(GATEWAYMAC)
                 .setEthDst(port.macAddress())
                 .setIpDst(floatingIP.fixedIpAddress())
                 .setTunnelId(getVni(port.networkId()))
diff --git a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
index 0181bde..b37df09 100644
--- a/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
+++ b/apps/openstacknetworking/openstackswitching/src/main/java/org/onosproject/openstacknetworking/switching/OpenstackSwitchingManager.java
@@ -126,6 +126,7 @@
     public static final Ip4Address DNS_SERVER_IP = Ip4Address.valueOf("8.8.8.8");
     private static final String FORWARD_SLASH = "/";
     private static final int DHCP_INFINITE_LEASE = -1;
+    public static final String SONA_DRIVER_NAME = "sona";
 
 
     private ApplicationId appId;
@@ -418,8 +419,12 @@
 
         @Override
         public void process(PacketContext context) {
+            // FIXME: use GatewayNode list to check if the ARP packet is from GatewayNode's
             if (context.isHandled()) {
                 return;
+            } else if (!SONA_DRIVER_NAME.equals(driverService
+                    .getDriver(context.inPacket().receivedFrom().deviceId()).name())) {
+                return;
             }
 
             InboundPacket pkt = context.inPacket();