1. Added SegmentRoutingManager so that it can spawn any required objects such as ArpHandler or IcmpHandler
 2. Added ArpHandler.java so that it handles any ICMP request for any known host

Change-Id: Ifd93318dc4c67fde2fce2fde04fa9df33d231e41
diff --git a/src/main/java/net/onrc/onos/core/hostmanager/Host.java b/src/main/java/net/onrc/onos/core/hostmanager/Host.java
index 45452e0..0f20fac 100644
--- a/src/main/java/net/onrc/onos/core/hostmanager/Host.java
+++ b/src/main/java/net/onrc/onos/core/hostmanager/Host.java
@@ -48,6 +48,12 @@
     private MACAddress macAddress;
 
     /**
+     * The IP address associated with this entity.
+     */
+    private int ipAddress;
+
+
+    /**
      * The VLAN tag on this entity, or null if untagged.
      */
     private Short vlan;
@@ -81,14 +87,16 @@
      * Create a new host and its information.
      *
      * @param macAddress mac address of this host
+     * @param ipAddress ip address of this host (if any)
      * @param vlan vlan ID of this host
      * @param switchDPID switch DPID where the host is attached
      * @param switchPort port number where the host is attached
      * @param lastSeenTimestamp last packet-in time of this host
      */
-    public Host(MACAddress macAddress, Short vlan, Long switchDPID,
+    public Host(MACAddress macAddress, int ipAddress, Short vlan, Long switchDPID,
             Long switchPort, Date lastSeenTimestamp) {
         this.macAddress = macAddress;
+        this.ipAddress = ipAddress;
         this.vlan = vlan;
         this.switchDPID = switchDPID;
         this.switchPort = switchPort;
@@ -107,6 +115,10 @@
         return macAddress;
     }
 
+    public int getIpAddress() {
+        return ipAddress;
+    }
+
     public Short getVlan() {
         return vlan;
     }
@@ -135,6 +147,7 @@
         final int prime = 31;
         hashCode = 1;
         hashCode = prime * hashCode + (int) (macAddress.toLong() ^ (macAddress.toLong() >>> 32));
+        hashCode = prime * hashCode + ipAddress;
         hashCode = prime * hashCode + ((switchDPID == null) ? 0 : switchDPID.hashCode());
         hashCode = prime * hashCode + ((switchPort == null) ? 0 : switchPort.hashCode());
         hashCode = prime * hashCode + ((vlan == null) ? 0 : vlan.hashCode());
@@ -159,6 +172,9 @@
         if (!Objects.equals(macAddress, other.macAddress)) {
             return false;
         }
+        if (!Objects.equals(ipAddress, other.ipAddress)) {
+            return false;
+        }
         if (!Objects.equals(switchDPID, other.switchDPID)) {
             return false;
         }
@@ -176,6 +192,8 @@
         StringBuilder builder = new StringBuilder();
         builder.append("Host [macAddress=");
         builder.append(macAddress.toString());
+        builder.append(", ipAddressn=");
+        builder.append(ipAddress);
         builder.append(", vlan=");
         builder.append(vlan);
         builder.append(", switchDPID=");
diff --git a/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java b/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java
index 155c3cf..e555ab5 100644
--- a/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java
+++ b/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java
@@ -23,10 +23,12 @@
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.core.packet.ARP;
 import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.packet.IPv4;
 import net.onrc.onos.core.topology.ITopologyService;
-import net.onrc.onos.core.topology.Port;
 import net.onrc.onos.core.topology.MutableTopology;
+import net.onrc.onos.core.topology.Port;
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.PortNumberUtils;
@@ -34,6 +36,7 @@
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPacketIn;
 import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.types.IPv4Address;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -214,14 +217,26 @@
     protected Host getSourceHostFromPacket(Ethernet eth,
             long swdpid, long port) {
         MACAddress sourceMac = eth.getSourceMAC();
+        int sourceIp = 0;
+
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
+            IPv4 ipv4 = (IPv4)eth.getPayload();
+            sourceIp = ipv4.getSourceAddress();
+        }
+        else if (eth.getEtherType() == Ethernet.TYPE_ARP) {
+            ARP arp = (ARP)eth.getPayload();
+            sourceIp = IPv4Address.of(arp.getSenderProtocolAddress()).getInt();
+        }
 
         // Ignore broadcast/multicast source
-        if (sourceMac.isBroadcast() || sourceMac.isBroadcast()) {
+        if (sourceMac.isBroadcast() || sourceMac.isMulticast()) {
             return null;
         }
 
         short vlan = eth.getVlanID();
         return new Host(sourceMac,
+                sourceIp,
                 ((vlan >= 0) ? vlan : null),
                 swdpid,
                 port,
@@ -287,6 +302,7 @@
             for (Port switchPort : host.getAttachmentPoints()) {
                 // We don't handle vlan now and multiple attachment points.
                 deleteHost = new Host(host.getMacAddress(),
+                        host.getIpAddress(),
                         null,
                         switchPort.getDpid().value(),
                         switchPort.getNumber().value(),
diff --git a/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java b/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java
index 274c7ed..63ff94e 100644
--- a/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java
+++ b/src/main/java/net/onrc/onos/core/topology/BaseTopologyAdaptor.java
@@ -261,7 +261,7 @@
         }
         List<Host> list = new ArrayList<>(hosts.size());
         for (HostData elm : hosts) {
-            list.add(new HostImpl(internalTopology, elm.getMac()));
+            list.add(new HostImpl(internalTopology, elm.getMac(), elm.getIp()));
         }
         return list;
     }
diff --git a/src/main/java/net/onrc/onos/core/topology/Host.java b/src/main/java/net/onrc/onos/core/topology/Host.java
index 4e0c2e4..eda41ae 100644
--- a/src/main/java/net/onrc/onos/core/topology/Host.java
+++ b/src/main/java/net/onrc/onos/core/topology/Host.java
@@ -23,6 +23,14 @@
     public MACAddress getMacAddress();
 
     /**
+     * Gets the Host IP address.
+     *
+     * @return the Host IP address.
+     */
+    public int getIpAddress();
+
+
+    /**
      * Gets the Host attachment points.
      * <p/>
      * TODO: There is only 1 attachment point right now.
diff --git a/src/main/java/net/onrc/onos/core/topology/HostData.java b/src/main/java/net/onrc/onos/core/topology/HostData.java
index d799113..e790134 100644
--- a/src/main/java/net/onrc/onos/core/topology/HostData.java
+++ b/src/main/java/net/onrc/onos/core/topology/HostData.java
@@ -1,5 +1,7 @@
 package net.onrc.onos.core.topology;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -12,7 +14,6 @@
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.SwitchPort;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
 /**
@@ -22,6 +23,7 @@
 public class HostData extends TopologyElement<HostData> {
 
     private final MACAddress mac;
+    private final int ip;
     private List<SwitchPort> attachmentPoints;
     private long lastSeenTime;
 
@@ -31,6 +33,7 @@
     @Deprecated
     protected HostData() {
         mac = null;
+        ip = 0;
     }
 
     /**
@@ -38,8 +41,9 @@
      *
      * @param mac the MAC address to identify the host
      */
-    public HostData(MACAddress mac) {
+    public HostData(MACAddress mac, int ip) {
         this.mac = checkNotNull(mac);
+        this.ip = ip;
         this.attachmentPoints = new LinkedList<>();
     }
 
@@ -53,6 +57,7 @@
     public HostData(HostData original) {
         super(original);
         this.mac = original.mac;
+        this.ip = original.ip;
         this.attachmentPoints = new ArrayList<>(original.attachmentPoints);
         this.lastSeenTime = original.lastSeenTime;
     }
@@ -67,6 +72,15 @@
     }
 
     /**
+     * Gets the host IP address.
+     *
+     * @return the IP address.
+     */
+    public int getIp() {
+        return ip;
+    }
+
+    /**
      * Gets the switch attachment points.
      *
      * @return the switch attachment points
@@ -185,11 +199,12 @@
         HostData other = (HostData) o;
         // XXX lastSeenTime excluded from Equality condition, is it OK?
         return Objects.equals(mac, other.mac) &&
+                ip == other.ip &&
                 Objects.equals(this.attachmentPoints, other.attachmentPoints);
     }
 
     @Override
     public String toString() {
-        return "[HostData " + mac + " attachmentPoints:" + attachmentPoints + "]";
+        return "[HostData " + mac + "(ip:" + ip + ")" + " attachmentPoints:" + attachmentPoints + "]";
     }
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/HostImpl.java b/src/main/java/net/onrc/onos/core/topology/HostImpl.java
index e45e015..1023806 100644
--- a/src/main/java/net/onrc/onos/core/topology/HostImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/HostImpl.java
@@ -1,9 +1,10 @@
 package net.onrc.onos.core.topology;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.core.util.SwitchPort;
 
@@ -13,6 +14,7 @@
 public class HostImpl extends TopologyObject implements Host {
 
     private final MACAddress id;
+    private final int ipAddress;
 
 
     /**
@@ -24,6 +26,20 @@
     HostImpl(BaseInternalTopology topology, MACAddress mac) {
         super(topology);
         this.id = checkNotNull(mac);
+        this.ipAddress = 0;
+    }
+
+    /**
+     * Creates a Host handler object.
+     *
+     * @param topology Topology instance this object belongs to
+     * @param mac MAC address of the host
+     * @param ipv4Address IP address of ths host
+     */
+    HostImpl(BaseInternalTopology topology, MACAddress mac, int ipv4Address) {
+        super(topology);
+        this.id = checkNotNull(mac);
+        this.ipAddress = ipv4Address;
     }
 
     @Override
@@ -93,4 +109,14 @@
     public AdminStatus getStatus() {
         return AdminStatus.ACTIVE;
     }
+
+
+    /**
+     *  Returns the IP address of the Host
+     */
+    @Override
+    public int getIpAddress() {
+        // TODO Auto-generated method stub
+        return ipAddress;
+    }
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
index 2ceb2d9..9efd911 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyImpl.java
@@ -10,9 +10,9 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.SortedSet;
 import java.util.TreeSet;
-import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.locks.Lock;
@@ -369,7 +369,7 @@
         }
         List<Host> list = new ArrayList<>(events.size());
         for (HostData elm : events) {
-            list.add(new HostImpl(this, elm.getMac()));
+            list.add(new HostImpl(this, elm.getMac(), elm.getIp()));
         }
         return list;
     }
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
index 5838483..c53ab76 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
@@ -614,7 +614,7 @@
         SwitchPort sp = new SwitchPort(host.getSwitchDPID(), host.getSwitchPort());
         List<SwitchPort> spLists = new ArrayList<SwitchPort>();
         spLists.add(sp);
-        HostData hostData = new HostData(host.getMacAddress());
+        HostData hostData = new HostData(host.getMacAddress(), host.getIpAddress());
         hostData.setAttachmentPoints(spLists);
         hostData.setLastSeenTime(host.getLastSeenTimestamp().getTime());
         // Does not use vlan info now.