Do not topology refresh when Host Added event happens
 Send ARP request only to the subnet of the target address

Change-Id: I9ab1b8108302764134646c661c7a763f791d4b19
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/ArpHandler.java b/src/main/java/net/onrc/onos/apps/segmentrouting/ArpHandler.java
index b724e27..0a8c316 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/ArpHandler.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/ArpHandler.java
@@ -148,12 +148,13 @@
             targetMac = MACAddress.valueOf(switchMacAddressStr);
         	log.debug("ArpHandler: Received a ARP query for a sw {} ", sw.getDpid());
     	}
-
-    	Host knownHost = isArpReqForKnownHost(sw, arpRequest);
-    	if (knownHost != null) {
-            targetMac = knownHost.getMacAddress();
-        	log.debug("ArpHandler: Received a ARP query for a known host {} ",
-        						IPv4Address.of(knownHost.getIpAddress()));
+    	else {
+        	Host knownHost = isArpReqForKnownHost(sw, arpRequest);
+        	if (knownHost != null) {
+                targetMac = knownHost.getMacAddress();
+            	log.debug("ArpHandler: Received a ARP query for a known host {} ",
+            						IPv4Address.of(knownHost.getIpAddress()));
+        	}
     	}
 
     	if (targetMac != null) {
@@ -183,9 +184,11 @@
     		 * that subnets are connected to except the port from which
     		 * ARP request is received
     		 */
+    	    IPv4Address targetAddress =
+    	            IPv4Address.of(arpRequest.getTargetProtocolAddress());
         	log.debug("ArpHandler: Received a ARP query for unknown host {} ",
         			IPv4Address.of(arpRequest.getTargetProtocolAddress()));
-    		for (Integer portNo : getSwitchSubnetPorts(sw)) {
+    		for (Integer portNo : getSwitchSubnetPorts(sw, targetAddress)) {
     			if (portNo.shortValue() == inPort.getPortNumber().shortValue())
     				continue;
             	log.debug("ArpHandler: Sending ARP request on switch {} port {}",
@@ -265,15 +268,18 @@
         return gatewayIps;
     }
 
-    private HashSet<Integer> getSwitchSubnetPorts(Switch sw) {
+    private HashSet<Integer> getSwitchSubnetPorts(Switch sw, IPv4Address targetAddress) {
         HashSet<Integer> switchSubnetPorts = new HashSet<Integer>();
 
         String subnets = sw.getStringAttribute("subnets");
         try {
             JSONArray arry = new JSONArray(subnets);
             for (int i = 0; i < arry.length(); i++) {
-                Integer subnetPort = (Integer)arry.getJSONObject(i).get("portNo");
-                switchSubnetPorts.add(subnetPort);
+                String subnetIpSlash = (String) arry.getJSONObject(i).get("subnetIp");
+                if (srManager.netMatch(subnetIpSlash, targetAddress.toString())) {
+                    Integer subnetPort = (Integer)arry.getJSONObject(i).get("portNo");
+                    switchSubnetPorts.add(subnetPort);
+                }
             }
         } catch (JSONException e) {
             // TODO Auto-generated catch block
@@ -324,7 +330,7 @@
 		 * that subnets are connected to except the port from which
 		 * ARP request is received
 		 */
-		for (Integer portNo : getSwitchSubnetPorts(sw)) {
+		for (Integer portNo : getSwitchSubnetPorts(sw, targetAddress)) {
 			if (portNo.shortValue() == inPort.getPortNumber().shortValue())
 				continue;
         	log.debug("ArpHandler: Sending ARP request on switch {} port {}",
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
index 053ba8a..89ce633 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -237,9 +237,17 @@
      */
     public void topologyEvents(TopologyEvents topologyEvents)
     {
-        if (topologyEvents.getAddedLinkDataEntries() != null)
-        {
-            discoveryTask.reschedule(1, TimeUnit.SECONDS);
+
+        Collection<LinkData> linkEntriesAdded =
+                topologyEvents.getAddedLinkDataEntries();
+        if (!linkEntriesAdded.isEmpty()) {
+            processLinkAdd(linkEntriesAdded);
+        }
+
+        Collection<PortData> PortEntriesAdded =
+                topologyEvents.getAddedPortDataEntries();
+        if (linkEntriesAdded != null) {
+            processPortAdd(PortEntriesAdded);
         }
 
         Collection<PortData> portEntries =
@@ -248,14 +256,57 @@
             processPortRemoval(portEntries);
         }
 
-        Collection<LinkData> linkEntries =
+        Collection<LinkData> linkEntriesRemoved =
                 topologyEvents.getRemovedLinkDataEntries();
-        if (!linkEntries.isEmpty()) {
-            processLinkRemoval(linkEntries);
+        if (!linkEntriesRemoved.isEmpty()) {
+            processLinkRemoval(linkEntriesRemoved);
         }
     }
 
     /**
+     * Report ports newly added to driver
+     *
+     * @param portEntries
+     */
+    private void processPortAdd(Collection<PortData> portEntries) {
+        //TODO: do we need to add ports slowly?
+        for (PortData port: portEntries) {
+            Dpid dpid = port.getDpid();
+            int portNo = (int) port.getPortNumber().value();
+
+            IOF13Switch sw13 = (IOF13Switch)floodlightProvider.getMasterSwitch(
+                    getSwId(port.getDpid().toString()));
+            //sw13.addPort(portNo);
+            log.debug("Add port {} to switch {}", portNo, dpid.toString());
+        }
+    }
+
+    /**
+     * Reports ports of new links to driver and recalculate ECMP SPG
+     *
+     * @param linkEntries
+     */
+    private void processLinkAdd(Collection<LinkData> linkEntries) {
+
+        // TODO: How to determine this link was broken before and back now
+        // If so, we need to ad the link slowly...
+        // Or, just add any new or restored link slowly ???
+        for (LinkData link: linkEntries) {
+            SwitchPort srcPort = link.getSrc();
+            SwitchPort dstPort = link.getDst();
+
+            IOF13Switch sw13src = (IOF13Switch)floodlightProvider.getMasterSwitch(
+                    getSwId(srcPort.getDpid().toString()));
+            IOF13Switch sw13dst = (IOF13Switch)floodlightProvider.getMasterSwitch(
+                    getSwId(srcPort.getDpid().toString()));
+            //sw13src.addPort(srcPort);
+            //sw13dst.addPort(dstPort);
+
+        }
+        discoveryTask.reschedule(1, TimeUnit.SECONDS);
+    }
+
+    /**
      * Check if all links are gone b/w the two switches.
      * If all links are gone, then we need to recalculate the path.
      * Otherwise, just report link failure to the driver.
@@ -264,20 +315,27 @@
      */
     private void processLinkRemoval(Collection<LinkData> linkEntries) {
         for (LinkData link: linkEntries) {
-            Dpid srcSwDpid = link.getSrc().getDpid();
-            Dpid dstSwDpid = link.getDst().getDpid();
+            SwitchPort srcPort = link.getSrc();
+            SwitchPort dstPort = link.getDst();
 
-            Switch srcSwitch = mutableTopology.getSwitch(srcSwDpid);
-            if (srcSwitch.getLinkToNeighbor(dstSwDpid) == null) {
+            IOF13Switch sw13src = (IOF13Switch)floodlightProvider.getMasterSwitch(
+                    getSwId(srcPort.getDpid().toString()));
+            IOF13Switch sw13dst = (IOF13Switch)floodlightProvider.getMasterSwitch(
+                    getSwId(srcPort.getDpid().toString()));
+            //sw13src.addPort(srcPort);
+            //sw13dst.addPort(dstPort);
+
+            Switch srcSwitch = mutableTopology.getSwitch(srcPort.getDpid());
+            if (srcSwitch.getLinkToNeighbor(dstPort.getDpid()) == null) {
                 discoveryTask.reschedule(1, TimeUnit.SECONDS);
-                log.debug("All links are gone b/w {} and {}",srcSwDpid,
-                        dstSwDpid);
+                log.debug("All links are gone b/w {} and {}",srcPort.getDpid(),
+                        srcPort.getDpid());
             }
         }
     }
 
     /**
-     * report ports removed to the driver
+     * report ports removed to the driver immediately
      *
      * @param portEntries
      */