Renamed devicemanager, flowprogrammer, linkdiscovery and util packages

net.onrc.onos.ofcontroller.devicemanager.* => net.onrc.onos.core.devicemanager.*
net.onrc.onos.ofcontroller.flowprogrammer.* => net.onrc.onos.core.flowprogrammer.*
net.onrc.onos.ofcontroller.linkdiscovery.* => net.onrc.onos.core.linkdiscovery.*
net.onrc.onos.ofcontroller.util.* => net.onrc.onos.core.util.*

Change-Id: Iaa865af552e8fb3a589e73d006569ac79f5a0f08
diff --git a/src/main/java/net/onrc/onos/core/devicemanager/IOnosDeviceListener.java b/src/main/java/net/onrc/onos/core/devicemanager/IOnosDeviceListener.java
new file mode 100644
index 0000000..69b340b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/devicemanager/IOnosDeviceListener.java
@@ -0,0 +1,7 @@
+package net.onrc.onos.core.devicemanager;
+
+public interface IOnosDeviceListener {
+
+    public void onosDeviceAdded(OnosDevice device);
+    public void onosDeviceRemoved(OnosDevice device);
+}
diff --git a/src/main/java/net/onrc/onos/core/devicemanager/IOnosDeviceService.java b/src/main/java/net/onrc/onos/core/devicemanager/IOnosDeviceService.java
new file mode 100644
index 0000000..f343308
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/devicemanager/IOnosDeviceService.java
@@ -0,0 +1,24 @@
+package net.onrc.onos.core.devicemanager;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.util.MACAddress;
+
+/**
+ * {@link OnosDeviceManager} doesn't yet provide any API to fellow modules,
+ * however making it export a dummy service means we can specify it as 
+ * a dependency of Forwarding
+ * @author jono
+ *
+ */
+public interface IOnosDeviceService extends IFloodlightService {
+
+	public void addOnosDeviceListener(IOnosDeviceListener listener);
+	
+	public void deleteOnosDeviceListener(IOnosDeviceListener listener);	
+	
+	public void deleteOnosDevice(OnosDevice dev);
+
+	public void deleteOnosDeviceByMac(MACAddress mac);
+	
+	public void addOnosDevice(Long mac, OnosDevice dev);
+}
diff --git a/src/main/java/net/onrc/onos/core/devicemanager/OnosDevice.java b/src/main/java/net/onrc/onos/core/devicemanager/OnosDevice.java
new file mode 100644
index 0000000..4e6a8dc
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/devicemanager/OnosDevice.java
@@ -0,0 +1,264 @@
+/**
+l*    Copyright 2011,2012, Big Switch Networks, Inc. 
+*    Originally created by David Erickson, Stanford University
+* 
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+
+package net.onrc.onos.core.devicemanager;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.packet.IPv4;
+
+/**
+ * An entity on the network is a visible trace of a device that corresponds
+ * to a packet received from a particular interface on the edge of a network,
+ * with a particular VLAN tag, and a particular MAC address, along with any
+ * other packet characteristics we might want to consider as helpful for
+ * disambiguating devices.
+ * 
+ * Entities are the most basic element of devices; devices consist of one or
+ * more entities.  Entities are immutable once created, except for the last
+ * seen timestamp.
+ *  
+ * @author readams
+ *
+ */
+public class OnosDevice implements Serializable { //implements Comparable<OnosDevice> {
+
+    private static int ACTIVITY_TIMEOUT = 30000;
+    
+    /**
+     * The MAC address associated with this entity
+     */
+    private MACAddress macAddress;
+    
+    /**
+     * The IP address associated with this entity, or null if no IP learned
+     * from the network observation associated with this entity
+     */
+    private Integer ipv4Address;
+    
+    /**
+     * The VLAN tag on this entity, or null if untagged
+     */
+    private Short vlan;
+    
+    /**
+     * The DPID of the switch for the ingress point for this entity,
+     * or null if not present
+     */
+    private long switchDPID;
+    
+    /**
+     * The port number of the switch for the ingress point for this entity,
+     * or null if not present
+     */
+    private short switchPort;
+    
+    /**
+     * The last time we observed this entity on the network
+     */
+    private Date lastSeenTimestamp;
+
+    private Date activeSince;
+    
+    private int hashCode = 0;
+
+    // ************
+    // Constructors
+    // ************
+     protected OnosDevice() {}
+     
+    /**
+     * Create a new entity
+     * 
+     * @param macAddress
+     * @param vlan
+     * @param ipv4Address
+     * @param switchDPID
+     * @param switchPort
+     * @param lastSeenTimestamp
+     */
+    public OnosDevice(MACAddress macAddress, Short vlan, 
+                  Integer ipv4Address, Long switchDPID, short switchPort, 
+                  Date lastSeenTimestamp) {
+        this.macAddress = macAddress;
+        this.ipv4Address = ipv4Address;
+        this.vlan = vlan;
+        this.switchDPID = switchDPID;
+        this.switchPort = switchPort;
+        this.lastSeenTimestamp = lastSeenTimestamp;
+        this.activeSince = lastSeenTimestamp;
+    }
+
+    // ***************
+    // Getters/Setters
+    // ***************
+
+    public MACAddress getMacAddress() {
+        return macAddress;
+    }
+
+    public Integer getIpv4Address() {
+        return ipv4Address;
+    }
+    
+    public void setIpv4Address(Integer ipv4Address) {
+    	this.ipv4Address = ipv4Address;
+    }
+
+    public Short getVlan() {
+        return vlan;
+    }
+
+    public Long getSwitchDPID() {
+        return switchDPID;
+    }
+    
+    public void setSwitchDPID(long dpid) {
+    	this.switchDPID = dpid;
+    }
+
+    public short getSwitchPort() {
+        return switchPort;
+    }
+    
+    public void setSwitchPort(short port) {
+    	this.switchPort = port;
+    }
+
+    public Date getLastSeenTimestamp() {
+        return lastSeenTimestamp;
+    }
+
+    
+    public void setLastSeenTimestamp(Date lastSeenTimestamp) {
+        if (activeSince == null ||
+            (activeSince.getTime() +  ACTIVITY_TIMEOUT) <
+                lastSeenTimestamp.getTime())
+            this.activeSince = lastSeenTimestamp;
+        this.lastSeenTimestamp = lastSeenTimestamp;
+    }
+
+    public Date getActiveSince() {
+        return activeSince;
+    }
+
+    public void setActiveSince(Date activeSince) {
+        this.activeSince = activeSince;
+    }
+    
+    @Override
+    public int hashCode() {
+        if (hashCode != 0) return hashCode;
+        final int prime = 31;
+        hashCode = 1;
+        hashCode = prime * hashCode
+                 + ((ipv4Address == null) ? 0 : ipv4Address.hashCode());
+        hashCode = prime * hashCode + (int) (macAddress.toLong() ^ (macAddress.toLong() >>> 32));
+        hashCode = prime * hashCode + (int)switchDPID;
+        hashCode = prime * hashCode + (int)switchPort;
+        hashCode = prime * hashCode + ((vlan == null) ? 0 : vlan.hashCode());
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        OnosDevice other = (OnosDevice) obj;
+        if (hashCode() != other.hashCode()) return false;
+        if (ipv4Address == null) {
+            if (other.ipv4Address != null) return false;
+        } else if (!ipv4Address.equals(other.ipv4Address)) return false; 
+        if (macAddress == null) {
+            if (other.macAddress != null) return false;
+        } else if (!macAddress.equals(other.macAddress)) return false;
+        if(switchDPID != other.switchDPID) return false;
+        if (switchPort != other.switchPort) return false;
+        if (vlan == null) {
+            if (other.vlan != null) return false;
+        } else if (!vlan.equals(other.vlan)) return false;
+        return true;
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Entity [macAddress=");
+        builder.append(macAddress.toString());
+        builder.append(", ipv4Address=");
+        builder.append(IPv4.fromIPv4Address(ipv4Address==null ?
+                       0 : ipv4Address.intValue()));
+        builder.append(", vlan=");
+        builder.append(vlan);
+        builder.append(", switchDPID=");
+        builder.append(switchDPID);
+        builder.append(", switchPort=");
+        builder.append(switchPort);
+        builder.append(", lastSeenTimestamp=");
+        builder.append(lastSeenTimestamp == null? "null" : lastSeenTimestamp.getTime());
+        builder.append(", activeSince=");
+        builder.append(activeSince == null? "null" : activeSince.getTime());
+        builder.append("]");
+        return builder.toString();
+    }
+
+    /*
+    @Override
+    public int compareTo(OnosDevice o) {
+        if (macAddress < o.macAddress) return -1;
+        if (macAddress > o.macAddress) return 1;
+
+        int r;
+        if (switchDPID == null)
+            r = o.switchDPID == null ? 0 : -1;
+        else if (o.switchDPID == null)
+            r = 1;
+        else
+            r = switchDPID.compareTo(o.switchDPID);
+        if (r != 0) return r;
+
+        if (switchPort == null)
+            r = o.switchPort == null ? 0 : -1;
+        else if (o.switchPort == null)
+            r = 1;
+        else
+            r = switchPort.compareTo(o.switchPort);
+        if (r != 0) return r;
+
+        if (ipv4Address == null)
+            r = o.ipv4Address == null ? 0 : -1;
+        else if (o.ipv4Address == null)
+            r = 1;
+        else
+            r = ipv4Address.compareTo(o.ipv4Address);
+        if (r != 0) return r;
+
+        if (vlan == null)
+            r = o.vlan == null ? 0 : -1;
+        else if (o.vlan == null)
+            r = 1;
+        else
+            r = vlan.compareTo(o.vlan);
+        if (r != 0) return r;
+
+        return 0;
+    }*/
+    
+}
diff --git a/src/main/java/net/onrc/onos/core/devicemanager/OnosDeviceManager.java b/src/main/java/net/onrc/onos/core/devicemanager/OnosDeviceManager.java
new file mode 100644
index 0000000..e673674
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/devicemanager/OnosDeviceManager.java
@@ -0,0 +1,360 @@
+package net.onrc.onos.core.devicemanager;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFMessageListener;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IUpdate;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.core.datagrid.IDatagridService;
+import net.onrc.onos.core.datagrid.IEventChannel;
+import net.onrc.onos.core.datagrid.IEventChannelListener;
+import net.onrc.onos.packet.ARP;
+import net.onrc.onos.packet.DHCP;
+import net.onrc.onos.packet.Ethernet;
+import net.onrc.onos.packet.IPv4;
+import net.onrc.onos.packet.UDP;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketIn;
+import org.openflow.protocol.OFType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OnosDeviceManager implements IFloodlightModule,
+					  IOFMessageListener,
+					  IOnosDeviceService,
+					  IEventChannelListener<Long, OnosDevice> {
+	protected final static Logger log = LoggerFactory.getLogger(OnosDeviceManager.class);
+	private static final int CLEANUP_SECOND = 60*60;
+	private static final int AGEING_MILLSEC = 60*60*1000;
+
+	private CopyOnWriteArrayList<IOnosDeviceListener> deviceListeners;
+	private IFloodlightProviderService floodlightProvider;
+	private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+
+	private IDatagridService datagrid;
+	private IEventChannel<Long, OnosDevice> eventChannel;
+	private static final String DEVICE_CHANNEL_NAME = "onos.device";
+	private Map<Long, OnosDevice> mapDevice = new ConcurrentHashMap<Long, OnosDevice>();
+	private INetworkGraphService networkGraphService;
+	private NetworkGraph networkGraph;
+
+    public enum OnosDeviceUpdateType {
+        ADD, DELETE, UPDATE;
+    }
+
+	private class OnosDeviceUpdate implements IUpdate {
+		private OnosDevice device;
+		private OnosDeviceUpdateType type;
+
+		public OnosDeviceUpdate(OnosDevice device, OnosDeviceUpdateType type) {
+			this.device = device;
+			this.type = type;
+		}
+
+		@Override
+		public void dispatch() {
+			if(type == OnosDeviceUpdateType.ADD) {
+				for(IOnosDeviceListener listener: deviceListeners) {
+					listener.onosDeviceAdded(device);
+				}
+			} else if (type == OnosDeviceUpdateType.DELETE){
+				for(IOnosDeviceListener listener: deviceListeners) {
+					listener.onosDeviceRemoved(device);
+				}
+			}
+		}
+	}
+
+	@Override
+	public String getName() {
+		return "onosdevicemanager";
+	}
+
+	@Override
+	public boolean isCallbackOrderingPrereq(OFType type, String name) {
+		// We want link discovery to consume LLDP first otherwise we'll
+		// end up reading bad device info from LLDP packets
+		return type == OFType.PACKET_IN && "linkdiscovery".equals(name);
+	}
+
+	@Override
+	public boolean isCallbackOrderingPostreq(OFType type, String name) {
+		return type == OFType.PACKET_IN &&
+				("proxyarpmanager".equals(name) || "onosforwarding".equals(name));
+	}
+
+	@Override
+	public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+		if (msg.getType().equals(OFType.PACKET_IN)) {
+			OFPacketIn pi = (OFPacketIn) msg;
+
+			Ethernet eth = IFloodlightProviderService.bcStore.
+					get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+
+			return processPacketIn(sw, pi, eth);
+		}
+
+		return Command.CONTINUE;
+	}
+
+	private Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+        long dpid =sw.getId();
+        short portId = pi.getInPort();
+        Long mac = eth.getSourceMAC().toLong();
+
+        OnosDevice srcDevice =
+                getSourceDeviceFromPacket(eth, dpid, portId);
+
+        if (srcDevice == null){
+        	return Command.STOP;
+        }
+
+        //We check if it is the same device in datagrid to suppress the device update
+        OnosDevice exDev = null;
+        if((exDev = mapDevice.get(mac)) != null ){
+	    	if(exDev.equals(srcDevice)) {
+	    		//There is the same existing device. Update only ActiveSince time.
+	        	exDev.setLastSeenTimestamp(new Date());
+	        	if(log.isTraceEnabled()) {
+			        log.debug("In the datagrid, there is the same device."
+							+ "Only update last seen time. dpid {}, port {}, mac {}, ip {}, lastSeenTime {}",
+			        		dpid, portId, srcDevice.getMacAddress(), srcDevice.getIpv4Address(), srcDevice.getLastSeenTimestamp().getTime());
+	        	}
+		        return Command.CONTINUE;
+	    	} else if (srcDevice.getIpv4Address() == null &&
+	    			exDev.getSwitchDPID().equals(srcDevice.getSwitchDPID()) &&
+	    			exDev.getSwitchPort() == srcDevice.getSwitchPort()) {
+	    			//Vlan should be handled based on the Onos spec. Until then, don't handle it.
+		    		//Device attachment point and mac address are the same
+		    		//but the packet does not have an ip address.
+		        	exDev.setLastSeenTimestamp(new Date());
+		        	if(log.isTraceEnabled()) {
+			        	log.debug("In the datagrid, there is the same device with no ip."
+								+ "Keep ip and update last seen time. dpid {}, port {}, mac {}, ip {} lastSeenTime {}",
+								dpid, portId, srcDevice.getMacAddress(), exDev.getIpv4Address(), srcDevice.getLastSeenTimestamp().getTime());
+		        	}
+		        	return Command.CONTINUE;
+	    		}
+	    	}
+
+        //If the switch port we try to attach a new device already has a link, then stop adding device
+        if(networkGraph.getLink(dpid, (long)portId) != null) {
+			if(log.isTraceEnabled()) {
+    			log.debug("Stop adding OnosDevice {} due to there is a link to: dpid {} port {}",
+						srcDevice.getMacAddress(), dpid, portId);
+			}
+			return Command.CONTINUE;
+        }
+
+        addOnosDevice(mac, srcDevice);
+
+        if(log.isTraceEnabled()) {
+	        log.debug("Add device info in the set. dpid {}, port {}, mac {}, ip {}, lastSeenTime {}",
+	       		dpid, portId, srcDevice.getMacAddress(), srcDevice.getIpv4Address(), srcDevice.getLastSeenTimestamp().getTime());
+        }
+        return Command.CONTINUE;
+	}
+
+     //Thread to delete devices periodically.
+	 //Remove all devices from the map first and then finally delete devices from the DB.
+	private class CleanDevice implements Runnable {
+		@Override
+		public void run() {
+			log.debug("called CleanDevice");
+			try{
+		        	Set<OnosDevice> deleteSet = new HashSet<OnosDevice>();
+			        for (OnosDevice dev : mapDevice.values() ) {
+			        	long now = new Date().getTime();
+			        	if((now - dev.getLastSeenTimestamp().getTime() > AGEING_MILLSEC)) {
+			        		if(log.isTraceEnabled()) {
+			        			log.debug("Remove device info in the datagrid. dpid {}, port {}, mac {}, ip {}, lastSeenTime {}, diff {}",
+				        				dev.getSwitchDPID(), dev.getSwitchPort(), dev.getMacAddress(), dev.getIpv4Address(),
+				        				dev.getLastSeenTimestamp().getTime(), now - dev.getLastSeenTimestamp().getTime());
+			        		}
+			        		deleteSet.add(dev);
+			        	}
+			        }
+
+			        for(OnosDevice dev : deleteSet) {
+			        	deleteOnosDevice(dev);
+			        }
+			 } catch(Exception e) {
+		    	 log.error("Error:", e);
+		     }
+		}
+	}
+
+    /**
+     * Get IP address from packet if the packet is either an ARP
+     * or a DHCP packet
+     * @param eth
+     * @param dlAddr
+     * @return
+     */
+    private int getSrcNwAddr(Ethernet eth, long dlAddr) {
+        if (eth.getPayload() instanceof ARP) {
+            ARP arp = (ARP) eth.getPayload();
+            if ((arp.getProtocolType() == ARP.PROTO_TYPE_IP) &&
+                    (Ethernet.toLong(arp.getSenderHardwareAddress()) == dlAddr)) {
+                return IPv4.toIPv4Address(arp.getSenderProtocolAddress());
+            }
+        } else if (eth.getPayload() instanceof IPv4) {
+            IPv4 ipv4 = (IPv4) eth.getPayload();
+            if (ipv4.getPayload() instanceof UDP) {
+                UDP udp = (UDP)ipv4.getPayload();
+                if (udp.getPayload() instanceof DHCP) {
+                    DHCP dhcp = (DHCP)udp.getPayload();
+                    if (dhcp.getOpCode() == DHCP.OPCODE_REPLY) {
+                        return ipv4.getSourceAddress();
+                    }
+                }
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Parse an entity from an {@link Ethernet} packet.
+     * @param eth the packet to parse
+     * @param sw the switch on which the packet arrived
+     * @param pi the original packetin
+     * @return the entity from the packet
+     */
+    private OnosDevice getSourceDeviceFromPacket(Ethernet eth,
+                                             long swdpid,
+                                             short port) {
+        byte[] dlAddrArr = eth.getSourceMACAddress();
+        long dlAddr = Ethernet.toLong(dlAddrArr);
+
+        // Ignore broadcast/multicast source
+        if ((dlAddrArr[0] & 0x1) != 0)
+            return null;
+
+        short vlan = eth.getVlanID();
+        int nwSrc = getSrcNwAddr(eth, dlAddr);
+        return new OnosDevice(MACAddress.valueOf(dlAddr),
+                          ((vlan >= 0) ? vlan : null),
+                          ((nwSrc != 0) ? nwSrc : null),
+                          swdpid,
+                          port,
+                          new Date());
+    }
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		List<Class<? extends IFloodlightService>> services =
+				new ArrayList<Class<? extends IFloodlightService>>();
+		services.add(IOnosDeviceService.class);
+		return services;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+		Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
+				new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+		impls.put(IOnosDeviceService.class, this);
+		return impls;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		List<Class<? extends IFloodlightService>> dependencies =
+				new ArrayList<Class<? extends IFloodlightService>>();
+		dependencies.add(IFloodlightProviderService.class);
+		dependencies.add(INetworkGraphService.class);
+		dependencies.add(IDatagridService.class);
+		return dependencies;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+		executor.scheduleAtFixedRate(new CleanDevice(), 30 ,CLEANUP_SECOND, TimeUnit.SECONDS);
+
+		deviceListeners = new CopyOnWriteArrayList<IOnosDeviceListener>();
+		datagrid = context.getServiceImpl(IDatagridService.class);
+		networkGraphService = context.getServiceImpl(INetworkGraphService.class);
+		networkGraph = networkGraphService.getNetworkGraph();
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context) {
+		floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
+		eventChannel = datagrid.addListener(DEVICE_CHANNEL_NAME, this,
+						    Long.class,
+						    OnosDevice.class);
+	}
+
+    @Override
+	public void deleteOnosDevice(OnosDevice dev) {
+	    Long mac = dev.getMacAddress().toLong();
+	    eventChannel.removeEntry(mac);
+	    floodlightProvider.publishUpdate(new OnosDeviceUpdate(dev, OnosDeviceUpdateType.DELETE));
+	}
+    
+    @Override
+	public void deleteOnosDeviceByMac(MACAddress mac) {
+    	OnosDevice deleteDevice = mapDevice.get(mac);
+    	deleteOnosDevice(deleteDevice);
+	}
+	
+	@Override
+	public void addOnosDevice(Long mac, OnosDevice dev) {
+	    eventChannel.addEntry(mac, dev);
+	    floodlightProvider.publishUpdate(new OnosDeviceUpdate(dev, OnosDeviceUpdateType.ADD));
+	}
+
+	@Override
+	public void entryAdded(OnosDevice dev) {
+	    Long mac = dev.getMacAddress().toLong();
+	    mapDevice.put(mac, dev);
+	    log.debug("Device added: device mac {}", mac);
+	}
+
+	@Override
+	public void entryRemoved(OnosDevice dev) {
+	    Long mac = dev.getMacAddress().toLong();
+	    mapDevice.remove(mac);
+	    log.debug("Device removed: device mac {}", mac);
+	}
+
+	@Override
+	public void entryUpdated(OnosDevice dev) {
+	    Long mac = dev.getMacAddress().toLong();
+	    mapDevice.put(mac, dev);
+	    log.debug("Device updated: device mac {}", mac);
+	}
+
+	@Override
+	public void addOnosDeviceListener(IOnosDeviceListener listener) {
+		deviceListeners.add(listener);
+	}
+
+	@Override
+	public void deleteOnosDeviceListener(IOnosDeviceListener listener) {
+		deviceListeners.remove(listener);
+	}
+}