- Send Barrier Request msg before we set the routing rules for the next iteration.
 - ICMP handler flush out any buffered packets when it receives the ICMP packets.

Change-Id: Id18b5fff37ddeb5cd56f14090a2b3dc99416bf6e
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java b/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java
index b35f402..3b65d55 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/IcmpHandler.java
@@ -143,12 +143,29 @@
                         /* TODO: We should not have come here as ARP itself
                          * would have installed a Route to the host. See if
                          * we can remove this code
+                         *  - It can happen when the rule is set later in switches
+                         *  (Ex: Ping reply arrives before the rules is set in the table)
+                         *  - The rule must be set by ARP handler. But, we set the rule
+                         *  again just in case and flush any pending packets to the host.
                          */
                         log.debug("ICMPHandler: ICMP request for known host {}",
                                          hostIpAddress);
                         byte[] destinationMacAddress = host.getMacAddress().toBytes();
                         srManager.addRouteToHost(sw,
                                 destinationAddress.getInt(), destinationMacAddress);
+
+                        byte[] destIp = destinationAddress.getBytes();
+                        for (IPv4 ipPacket: srManager.getIpPacketFromQueue(destIp)) {
+                            if (ipPacket != null && !inSameSubnet(sw, ipPacket)) {
+                                Ethernet eth = new Ethernet();
+                                eth.setDestinationMACAddress(payload.getSourceMACAddress());
+                                eth.setSourceMACAddress(sw.getStringAttribute("routerMac"));
+                                eth.setEtherType(Ethernet.TYPE_IPV4);
+                                eth.setPayload(ipPacket);
+                                sendPacketOut(sw, eth, inPort.getSwitchPort(), false);
+                            }
+                        }
+
                         return;
                     }
                 }
@@ -411,4 +428,54 @@
 
     }
 
+    /**
+     * Check if the source IP and destination IP are in the same subnet
+     *
+     * @param sw Switch
+     * @param ipv4 IP address to check
+     * @return return true if the IP packet is within the same subnet
+     */
+    private boolean inSameSubnet(Switch sw, IPv4 ipv4) {
+
+        String gwIpSrc = getGwIpForSubnet(ipv4.getSourceAddress());
+        String gwIpDest = getGwIpForSubnet(ipv4.getDestinationAddress());
+
+        if (gwIpSrc.equals(gwIpDest)) {
+            return true;
+        }
+        else
+            return false;
+    }
+
+    /**
+     * Get router IP address for the given IP address
+     *
+     * @param sourceAddress
+     * @return
+     */
+    private String getGwIpForSubnet(int sourceAddress) {
+
+        String gwIp = null;
+        IPv4Address srcIp = IPv4Address.of(sourceAddress);
+
+        for (Switch sw: mutableTopology.getSwitches()) {
+
+            String subnets = sw.getStringAttribute("subnets");
+            try {
+                JSONArray arry = new JSONArray(subnets);
+                for (int i = 0; i < arry.length(); i++) {
+                    String subnetIpSlash = (String) arry.getJSONObject(i).get("subnetIp");
+                    if (srManager.netMatch(subnetIpSlash, srcIp.toString())) {
+                        gwIp = subnetIpSlash;
+                    }
+                }
+            } catch (JSONException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+
+        return gwIp;
+    }
+
 }