Did porting of PROXYARP and Forwarding to the new-datamodel branch.

Change-Id: Ibbc46e20e31627daf68149b7cb31b055d3441eaf
diff --git a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java
index 546ec64..d94eb1f 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/OnosDevice.java
@@ -81,7 +81,8 @@
     // ************
     // Constructors
     // ************
-    
+     protected OnosDevice() {}
+     
     /**
      * Create a new entity
      * 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
index 294e1a5..1eb7750 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/forwarding/Forwarding.java
@@ -6,6 +6,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -20,20 +21,27 @@
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.datagrid.IDatagridService;
 import net.onrc.onos.datagrid.IEventChannel;
+import net.onrc.onos.datagrid.IEventChannelListener;
+import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.IntentMap;
+import net.onrc.onos.intent.IntentOperation;
+import net.onrc.onos.intent.IntentOperationList;
+import net.onrc.onos.intent.PathIntent;
+import net.onrc.onos.intent.ShortestPathIntent;
+import net.onrc.onos.intent.Intent.IntentState;
+import net.onrc.onos.intent.runtime.IPathCalcRuntimeService;
+import net.onrc.onos.intent.runtime.IntentStateList;
 import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceService;
 import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
+import net.onrc.onos.ofcontroller.networkgraph.Device;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
 import net.onrc.onos.ofcontroller.proxyarp.BroadcastPacketOutNotification;
 import net.onrc.onos.ofcontroller.proxyarp.IProxyArpService;
-import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
-import net.onrc.onos.ofcontroller.util.CallerId;
-import net.onrc.onos.ofcontroller.util.DataPath;
 import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
-import net.onrc.onos.ofcontroller.util.FlowId;
 import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.FlowPathType;
-import net.onrc.onos.ofcontroller.util.FlowPathUserState;
 import net.onrc.onos.ofcontroller.util.Port;
 import net.onrc.onos.ofcontroller.util.SwitchPort;
 import net.onrc.onos.packet.Ethernet;
@@ -54,35 +62,34 @@
 import com.google.common.collect.ListMultimap;
 
 public class Forwarding implements IOFMessageListener, IFloodlightModule,
-									IForwardingService {
+									IForwardingService, IEventChannelListener<Long, IntentStateList> {
 	private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
    
-	private final int IDLE_TIMEOUT = 5; // seconds
-	private final int HARD_TIMEOUT = 0; // seconds
 	private final int SLEEP_TIME_FOR_DB_DEVICE_INSTALLED = 100; // milliseconds
 	private final static int NUMBER_OF_THREAD_FOR_EXECUTOR = 1;
 	
 	private final static ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUMBER_OF_THREAD_FOR_EXECUTOR);
 	
-	private final CallerId callerId = new CallerId("Forwarding");
+	private final String callerId = "Forwarding";
 	
 	private IFloodlightProviderService floodlightProvider;
 	private IFlowPusherService flowPusher;
 	private IDatagridService datagrid;
-	//
-	// TODO: Using PacketOutNotification as both the key and the
-	// value is a hack that should be removed when this module is
-	// refactored.
-	//
-	private IEventChannel<PacketOutNotification, PacketOutNotification> eventChannel;
-	private static final String PACKET_OUT_CHANNEL_NAME = "onos.packet_out";
+
+	private IEventChannel<Long, BroadcastPacketOutNotification> eventChannel;
+	private static final String SINGLE_PACKET_OUT_CHANNEL_NAME = "onos.forwarding.packet_out";
 
 	private IControllerRegistryService controllerRegistryService;
 	
+	private INetworkGraphService networkGraphService;
+	private NetworkGraph networkGraph;
+	private IPathCalcRuntimeService pathRuntime;
+	private IntentMap intentMap;
+	
 	// TODO it seems there is a Guava collection that will time out entries.
 	// We should see if this will work here.
 	private Map<Path, PushedFlow> pendingFlows;
-	private ListMultimap<Long, PacketToPush> waitingPackets;
+	private ListMultimap<String, PacketToPush> waitingPackets;
 	
 	private final Object lock = new Object();
 	
@@ -97,12 +104,12 @@
 	}
 	
 	private class PushedFlow {
-		public final long flowId;
+		public final String intentId;
 		public boolean installed = false;
 		public short firstOutPort;
 		
-		public PushedFlow(long flowId) {
-			this.flowId = flowId;
+		public PushedFlow(String flowId) {
+			this.intentId = flowId;
 		}
 	}
 	
@@ -162,8 +169,11 @@
 				new ArrayList<Class<? extends IFloodlightService>>();
 		dependencies.add(IFloodlightProviderService.class);
 		dependencies.add(IFlowPusherService.class);
+		dependencies.add(IControllerRegistryService.class);	
 		dependencies.add(IOnosDeviceService.class);
-		dependencies.add(IControllerRegistryService.class);
+		dependencies.add(IDatagridService.class);
+		dependencies.add(INetworkGraphService.class);
+		dependencies.add(IPathCalcRuntimeService.class);
 		// We don't use the IProxyArpService directly, but reactive forwarding
 		// requires it to be loaded and answering ARP requests
 		dependencies.add(IProxyArpService.class);
@@ -177,6 +187,8 @@
 		flowPusher = context.getServiceImpl(IFlowPusherService.class);
 		datagrid = context.getServiceImpl(IDatagridService.class);
 		controllerRegistryService = context.getServiceImpl(IControllerRegistryService.class);
+		networkGraphService = context.getServiceImpl(INetworkGraphService.class);
+        pathRuntime = context.getServiceImpl(IPathCalcRuntimeService.class);
 		
 		floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
 
@@ -186,14 +198,13 @@
 	
 	@Override
 	public void startUp(FloodlightModuleContext context) {
-		//
-		// TODO: Using PacketOutNotification as both the key and the
-		// value is a hack that should be removed when this module is
-		// refactored.
-		//
-		eventChannel = datagrid.createChannel(PACKET_OUT_CHANNEL_NAME,
-						      PacketOutNotification.class,
-						      PacketOutNotification.class);
+
+		eventChannel = datagrid.createChannel(SINGLE_PACKET_OUT_CHANNEL_NAME,
+								Long.class,
+						      BroadcastPacketOutNotification.class);
+		networkGraph = networkGraphService.getNetworkGraph();
+		intentMap = pathRuntime.getPathIntents();
+		datagrid.addListener("onos.pathintent_state", this, Long.class, IntentStateList.class);
 	}
 
 	@Override
@@ -248,17 +259,13 @@
 			log.trace("Sending broadcast packet to other ONOS instances");
 		}
 
-		PacketOutNotification key =
+		//We don't use address information, so 0 is put into the third argument.
+		BroadcastPacketOutNotification key =
 		    new BroadcastPacketOutNotification(
 						       eth.serialize(),
-						       null, sw.getId(),
+						       0, sw.getId(),
 						       pi.getInPort());
-		//
-		// TODO: Using PacketOutNotification as both the key and the
-		// value is a hack that should be removed when this module is
-		// refactored.
-		//
-		eventChannel.addTransientEntry(key, key);
+		eventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
 	}
 	
 	private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth){
@@ -268,25 +275,18 @@
 				HexString.toHexString(eth.getDestinationMACAddress()); 
 		
 		//FIXME getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
-		// TODO: Fix the code below after deviceStorage was removed
-		/*
-		try{	
-			IDeviceObject deviceObject = deviceStorage.getDeviceByMac(
-				destinationMac);
-			if (deviceObject == null) {
-				log.debug("No device entry found for {}",
-						destinationMac);
+		Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(destinationMac));
 
-				//Device is not in the DB, so wait it until the device is added.
-				executor.schedule(new WaitDeviceArp(sw, pi, eth), SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, TimeUnit.MILLISECONDS);
-				return;
-			}
+		if (deviceObject == null) {
+			log.debug("No device entry found for {}",
+					destinationMac);
 
-			continueHandlePacketIn(sw, pi, eth, deviceObject);
-		} finally {
-			deviceStorage.rollback();
+			//Device is not in the DB, so wait it until the device is added.
+			executor.schedule(new WaitDeviceArp(sw, pi, eth), SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, TimeUnit.MILLISECONDS);
+			return;
 		}
-		*/
+
+		continueHandlePacketIn(sw, pi, eth, deviceObject);
 	}
 	
 	private class WaitDeviceArp implements Runnable {
@@ -303,44 +303,35 @@
 
 		@Override
 		public void run() {
-			// TODO: Fix the code below after deviceStorage was removed
-			/*
-			try {
-				IDeviceObject deviceObject = deviceStorage.getDeviceByMac(HexString.toHexString(eth.getDestinationMACAddress()));
-					if(deviceObject == null){
-						log.debug("wait {}ms and device was not found. Send broadcast packet and the thread finish.", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED);
-						handleBroadcast(sw, pi, eth);
-						return;
-					}
-					log.debug("wait {}ms and device {} was found, continue",SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, deviceObject.getMACAddress());
-					continueHandlePacketIn(sw, pi, eth, deviceObject);
-			} finally {
-				deviceStorage.rollback();
-			}
-			*/
+			Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(eth.getDestinationMACAddress()));
+				if(deviceObject == null){
+					log.debug("wait {}ms and device was not found. Send broadcast packet and the thread finish.", SLEEP_TIME_FOR_DB_DEVICE_INSTALLED);
+					handleBroadcast(sw, pi, eth);
+					return;
+				}
+				log.debug("wait {}ms and device {} was found, continue",SLEEP_TIME_FOR_DB_DEVICE_INSTALLED, deviceObject.getMacAddress());
+				continueHandlePacketIn(sw, pi, eth, deviceObject);
 		}
 	}
 
-	// TODO: Fix the code below because IDeviceObject was removed
-	/*
-	private void continueHandlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth, IDeviceObject deviceObject) {
-		log.debug("Start continuehandlePacketIn");
+	private void continueHandlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth, Device deviceObject) {
 
-		Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();	
+		log.debug("Start continuehandlePacketIn");
+		
+		//Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();	
+		Iterator<net.onrc.onos.ofcontroller.networkgraph.Port> ports = deviceObject.getAttachmentPoints().iterator();	
 		if (!ports.hasNext()) {
 			log.debug("No attachment point found for device {} - broadcasting packet", 
-					deviceObject.getMACAddress());
+					deviceObject.getMacAddress());
 			handleBroadcast(sw, pi, eth);
 			return;	
 		}
 
-
 		//This code assumes the device has only one port. It should be problem.
-		IPortObject portObject = ports.next();
-
-		short destinationPort = portObject.getNumber();
-		ISwitchObject switchObject = portObject.getSwitch();
-		long destinationDpid = HexString.toLong(switchObject.getDPID());
+		net.onrc.onos.ofcontroller.networkgraph.Port portObject = ports.next();
+		short destinationPort = portObject.getNumber().shortValue();
+		Switch switchObject = portObject.getSwitch();
+		long destinationDpid = switchObject.getDpid();
 		
 		// TODO SwitchPort, Dpid and Port should probably be immutable
 		SwitchPort srcSwitchPort = new SwitchPort(
@@ -351,21 +342,18 @@
 		MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
 		MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
 		
-		FlowPath flowPath;
-		
 		synchronized (lock) {
 			//TODO check concurrency
 			Path pathspec = new Path(srcMacAddress, dstMacAddress);	
-			
 			PushedFlow existingFlow = pendingFlows.get(pathspec);
 
 			//A path is installed side by side to reduce a path timeout and a wrong state.
 			if (existingFlow != null) {
 				// We've already start to install a flow for this pair of MAC addresses
 				if(log.isDebugEnabled()) {
-					log.debug("Found existing the same pathspec {}, Flow ID is {}", 
+					log.debug("Found existing the same pathspec {}, intent ID is {}", 
 							pathspec, 
-							HexString.toHexString(existingFlow.flowId));
+							existingFlow.intentId);
 				}
 				
 				OFPacketOut po = constructPacketOut(pi, sw);
@@ -378,42 +366,44 @@
 					// Flow has been sent to the switches so it is safe to
 					// send a packet out now
 
-					//
-					// TODO: The getFlow() call below needs
-					// to be updated to the new Path Intent
-					// framework.
-					//
-					// FlowPath flow = datagrid.getFlow(new FlowId(existingFlow.flowId));
-					FlowPath flow = null;
-					FlowEntry flowEntryForThisSwitch = null;
+					Intent intent = intentMap.getIntent(existingFlow.intentId);
+					PathIntent pathIntent = null;
+					if(intent instanceof PathIntent) {
+						pathIntent = (PathIntent)intent;
+					} else {
+						log.debug("Intent {} is not PathIntent. Return.", intent.getId());
+						return;
+					}
 					
-					if (flow != null) {
-						for (FlowEntry flowEntry : flow.flowEntries()) {
-							if (flowEntry.dpid().equals(new Dpid(sw.getId()))) {
-								flowEntryForThisSwitch = flowEntry;
-								break;
-							}
+					Boolean isflowEntryForThisSwitch = false;		
+					net.onrc.onos.ofcontroller.networkgraph.Path path = pathIntent.getPath();
+
+					for(Iterator<LinkEvent> i = path.iterator(); i.hasNext();) {
+						LinkEvent le = (LinkEvent)i.next();
+						if(le.getSrc().dpid == sw.getId()) {
+							log.debug("src {} dst {}", le.getSrc(), le.getDst());
+							isflowEntryForThisSwitch = true;
+							break;
 						}
 					}
 					
-					if (flowEntryForThisSwitch == null) {
+					if (isflowEntryForThisSwitch == false) {
 						// If we don't find a flow entry for that switch, then we're
 						// in the middle of a rerouting (or something's gone wrong). 
 						// This packet will be dropped as a victim of the rerouting.
-						log.debug("Dropping packet on flow {} between {}-{}, flow path {}",
-								new Object[] {new FlowId(existingFlow.flowId),
-								srcMacAddress, dstMacAddress, flow});
-					}
-					else {
-						log.debug("Sending packet out from sw {}, outport{}", sw, flowEntryForThisSwitch.outPort().value());
-						sendPacketOut(sw, po, flowEntryForThisSwitch.outPort().value());
+						log.debug("Dropping packet on flow {} between {}-{}",
+								existingFlow.intentId,
+								srcMacAddress, dstMacAddress);
+					} else {
+						log.debug("Sending packet out from sw {}, outport{}", sw, existingFlow.firstOutPort);
+						sendPacketOut(sw, po, existingFlow.firstOutPort);
 					}
 				}
 				else {
 					// Flow path has not yet been installed to switches so save the
 					// packet out for later
-					log.debug("Put a packet into the waitng list. flowId {}", Long.toHexString(existingFlow.flowId));
-					waitingPackets.put(existingFlow.flowId, new PacketToPush(po, sw.getId()));
+					log.debug("Put a packet into the waitng list. flowId {}", existingFlow.intentId);
+					waitingPackets.put(existingFlow.intentId, new PacketToPush(po, sw.getId()));
 				}
 				return;
 			}
@@ -421,42 +411,25 @@
 			log.debug("Adding new flow between {} at {} and {} at {}",
 					new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
 			
-			DataPath datapath = new DataPath();
-			datapath.setSrcPort(srcSwitchPort);
-			datapath.setDstPort(dstSwitchPort);
-			
-			flowPath = new FlowPath();
-			flowPath.setInstallerId(new CallerId(callerId));
-	
-			flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
-			flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
-			flowPath.setFlowEntryMatch(new FlowEntryMatch());
-			flowPath.setIdleTimeout(IDLE_TIMEOUT);
-			flowPath.setHardTimeout(HARD_TIMEOUT);
-			flowPath.flowEntryMatch().enableSrcMac(srcMacAddress);
-			flowPath.flowEntryMatch().enableDstMac(dstMacAddress);
-			flowPath.flowEntryMatch().enableEthernetFrameType(Ethernet.TYPE_IPv4);
-			flowPath.setDataPath(datapath);
-
-			FlowId flowId = new FlowId(controllerRegistryService.getNextUniqueId());
-			
-			flowPath.setFlowId(flowId);
+			String intentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
+	        IntentOperationList operations = new IntentOperationList();
+	        ShortestPathIntent intent = new ShortestPathIntent(intentId,
+	    			sw.getId(), pi.getInPort(), srcMacAddress.toLong(),
+	    			destinationDpid, destinationPort, dstMacAddress.toLong());
+	        IntentOperation.Operator operator = IntentOperation.Operator.ADD;
+	        operations.add(operator, intent);
+	        pathRuntime.executeIntentOperations(operations);
 
 			OFPacketOut po = constructPacketOut(pi, sw);
 			
 			// Add to waiting lists
-			pendingFlows.put(pathspec, new PushedFlow(flowId.value()));
-			log.debug("Put a Path {} in the pending flow, Flow ID {}", pathspec, flowId);
-			waitingPackets.put(flowId.value(), new PacketToPush(po, sw.getId()));
+			pendingFlows.put(pathspec, new PushedFlow(intentId));
+			log.debug("Put a Path {} in the pending flow, intent ID {}", pathspec, intentId);
+			waitingPackets.put(intentId, new PacketToPush(po, sw.getId()));
 			log.debug("Put a Packet in the wating list. related pathspec {}", pathspec);
+			
 		}
-
-		log.debug("Adding forward {} to {}. Flow ID {}", new Object[] {
-				srcMacAddress, dstMacAddress, flowPath.flowId()});
-		// TODO: Add the flow by using the new Path Intent framework
-		// flowService.addFlow(flowPath);
 	}
-	*/
 
 	private OFPacketOut constructPacketOut(OFPacketIn pi, IOFSwitch sw) {	
 		OFPacketOut po = new OFPacketOut();
@@ -479,94 +452,84 @@
 
 	@Override
 	public void flowsInstalled(Collection<FlowPath> installedFlowPaths) {
-		for (FlowPath flowPath : installedFlowPaths) {
-			flowInstalled(flowPath);
-		}
 	}
 	
 	@Override
 	public void flowRemoved(FlowPath removedFlowPath) {
-		if(log.isDebugEnabled()){
-			log.debug("Flow {} was removed", removedFlowPath.flowId());
+	}
+	
+	public void flowRemoved(PathIntent removedIntent) {
+		if(log.isTraceEnabled()){
+			log.trace("Path {} was removed", removedIntent.getParentIntent().getId());
 		}
 
-
-		if (!removedFlowPath.installerId().equals(callerId)) {
-			// Not our flow path, ignore
-			return;
-		}
-
-		MACAddress srcMacAddress = removedFlowPath.flowEntryMatch().srcMac();
-		MACAddress dstMacAddress = removedFlowPath.flowEntryMatch().dstMac();
-		
+		ShortestPathIntent spfIntent = (ShortestPathIntent) removedIntent.getParentIntent();
+		MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
+		MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
 		Path removedPath = new Path(srcMacAddress, dstMacAddress);
 		
 		synchronized (lock) {
 			// There *shouldn't* be any packets queued if the flow has 
 			// just been removed. 
-			List<PacketToPush> packets = waitingPackets.removeAll(removedFlowPath.flowId().value());
+			List<PacketToPush> packets = waitingPackets.removeAll(spfIntent.getId());
 			if (!packets.isEmpty()) {
-				log.warn("Removed flow {} has packets queued.",  removedFlowPath.flowId());
+				log.warn("Removed flow {} has packets queued.",  spfIntent.getId());
 			}
 			pendingFlows.remove(removedPath);
-			log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, removedFlowPath.flowId());
+			log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, spfIntent.getId());
 		}
 	}
-
-	private void flowInstalled(FlowPath installedFlowPath) {	
-		log.debug("Flow {} was installed", installedFlowPath.flowId());
-		
-		if (!installedFlowPath.installerId().equals(callerId)) {
-			// Not our flow path, ignore
-			return;
-		}	
-
-		if(installedFlowPath.flowEntries().isEmpty()){
-			//If there is no flowEntry, ignore
-			log.warn("There is no flowEntry in the installedFlowPath id {}.return.", installedFlowPath.flowId());
-			return;
+	
+	private void flowInstalled(PathIntent installedPath) {	
+		if(log.isTraceEnabled()){
+			log.trace("Path {} was installed", installedPath.getParentIntent().getId());
 		}
 		
-		MACAddress srcMacAddress = installedFlowPath.flowEntryMatch().srcMac();
-		MACAddress dstMacAddress = installedFlowPath.flowEntryMatch().dstMac();
-		Path installedPath = new Path(srcMacAddress, dstMacAddress);
+		ShortestPathIntent spfIntent = (ShortestPathIntent) installedPath.getParentIntent();
+		MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
+		MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
+		Path path = new Path(srcMacAddress, dstMacAddress);
+		log.debug("Path spec {}", path);
 		
 		// TODO waiting packets should time out. We could request a path that
 		// can't be installed right now because of a network partition. The path
 		// may eventually be installed, but we may have received thousands of 
 		// packets in the meantime and probably don't want to send very old packets.
 		
-		List<PacketToPush> packets;
-		Short outPort = installedFlowPath.flowEntries().get(0).outPort().value();
-
-		PushedFlow existingFlow;
+		List<PacketToPush> packets = null;
+		net.onrc.onos.ofcontroller.networkgraph.Path graphPath = installedPath.getPath();
+		
+		log.debug("path{}", graphPath);
+		Short outPort = graphPath.get(0).getSrc().getNumber().shortValue();
+	
+		PushedFlow existingFlow = null;
 		
 		synchronized (lock) {
-			existingFlow = pendingFlows.get(installedPath);
+			existingFlow = pendingFlows.get(path);
 
 			if (existingFlow != null) {
 			    existingFlow.installed = true;
 			    existingFlow.firstOutPort = outPort;
 			} else {
-				log.debug("ExistingFlow {} is null", installedPath);
+				log.debug("ExistingFlow {} is null", path);
 				return;
 			}
 
 			//Check both existing flow are installed status.
 			if(existingFlow.installed){
-				packets = waitingPackets.removeAll(existingFlow.flowId);
+				packets = waitingPackets.removeAll(existingFlow.intentId);
 				if(log.isDebugEnabled()){
 					log.debug("removed my packets {} to push from waitingPackets. outPort {} size {}",
-							Long.toHexString(existingFlow.flowId), existingFlow.firstOutPort, packets.size());
+							existingFlow.intentId, existingFlow.firstOutPort, packets.size());
 				}
 			}else{
 				log.debug("Forward or reverse flows hasn't been pushed yet. return");	
 				return;
 			}
 		}
-
+		
 		for (PacketToPush packet : packets) {
-			log.debug("Start packetToPush to sw {}, outPort {}", packet.dpid, existingFlow.firstOutPort);
+			log.debug("Start packetToPush to sw {}, outPort {}, path {}", packet.dpid, existingFlow.firstOutPort, path);
 			IOFSwitch sw = floodlightProvider.getSwitches().get(packet.dpid);
 			sendPacketOut(sw, packet.packet, existingFlow.firstOutPort);
 		}
@@ -581,4 +544,47 @@
 		flowPusher.add(sw, po);
 	}
 
+	@Override
+	public void entryAdded(IntentStateList value) {
+		entryUpdated(value);
+		
+	}
+
+	@Override
+	public void entryRemoved(IntentStateList value) {
+		//no-op
+	}
+
+	@Override
+	public void entryUpdated(IntentStateList value) {
+		for (Entry<String, IntentState> entry: value.entrySet()) {
+			log.debug("path intent key {}, value {}", entry.getKey(), entry.getValue());
+			PathIntent pathIntent = (PathIntent) intentMap.getIntent(entry.getKey());
+			if (pathIntent == null)
+				continue;
+			
+			if (!(pathIntent.getParentIntent() instanceof ShortestPathIntent))
+				continue;
+
+			IntentState state = entry.getValue();
+			switch (state) {
+				case INST_REQ:
+					break;
+				case INST_ACK:
+					flowInstalled(pathIntent);
+					break;
+				case INST_NACK:
+					break;
+				case DEL_REQ:
+					break;
+				case DEL_ACK:
+					flowRemoved(pathIntent);
+					break;
+				case DEL_PENDING:
+					break;
+				default:
+					break;
+				}
+		}
+	}
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java
index 48d04e0..081101e 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpReplyNotification.java
@@ -1,7 +1,6 @@
 package net.onrc.onos.ofcontroller.proxyarp;
 
 import java.io.Serializable;
-import java.net.InetAddress;
 
 import net.floodlightcontroller.util.MACAddress;
 
@@ -13,15 +12,16 @@
 
     private static final long serialVersionUID = 1L;
 
-    private InetAddress targetAddress;
+    private int targetAddress;
     private MACAddress targetMacAddress;
 
+    protected ArpReplyNotification() {}
     /**
      * Class constructor.
      * @param targetAddress IP address received from the ARP reply
      * @param targetMacAddress MAC address received from the ARP reply
      */
-    public ArpReplyNotification(InetAddress targetAddress,
+    public ArpReplyNotification(int targetAddress,
             MACAddress targetMacAddress) {
         this.targetAddress = targetAddress;
         this.targetMacAddress = targetMacAddress;
@@ -31,7 +31,7 @@
      * Returns the IP address of the ARP reply.
      * @return the IP address
      */
-    public InetAddress getTargetAddress() {
+    public int getTargetAddress() {
         return targetAddress;
     }
 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java
index 22fe965..387414b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/BroadcastPacketOutNotification.java
@@ -1,6 +1,6 @@
 package net.onrc.onos.ofcontroller.proxyarp;
 
-import java.net.InetAddress;
+
 
 // TODO This class is too generic to be handled by ProxyArpService.
 // TODO The generic broadcast packet shouldn't contain an IP address which is
@@ -16,10 +16,16 @@
 
     private static final long serialVersionUID = 1L;
 
-    private final InetAddress address;
+    private final int address;
     private final long inSwitch;
     private final short inPort;
 
+    protected BroadcastPacketOutNotification() {
+    	super();
+        this.address = -1;
+        this.inSwitch = -1;
+        this.inPort = -1;
+    }
     /**
      * Class constructor.
      *
@@ -32,7 +38,7 @@
      * @param inPort
      *        port number of the receiving port
      */
-    public BroadcastPacketOutNotification(byte[] packet, InetAddress address,
+    public BroadcastPacketOutNotification(byte[] packet, int address,
             long inSwitch, short inPort) {
         super(packet);
 
@@ -40,7 +46,7 @@
         this.inSwitch = inSwitch;
         this.inPort = inPort;
     }
-
+    
     /**
      * Get the dpid of the switch the packet was received on.
      *
@@ -65,7 +71,7 @@
      * @return the target IP address for ARP packets, or null if the packet is
      *         not an ARP packet
      */
-    public InetAddress getTargetAddress() {
+    public int getTargetAddress() {
         return address;
     }
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java
index a201939..fb550cb 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/PacketOutNotification.java
@@ -8,16 +8,20 @@
  * abstract base class that will be subclassed by specific types of
  * notifications.
  */
-public abstract class PacketOutNotification implements Serializable {
+public abstract class PacketOutNotification implements Serializable{
 
     private static final long serialVersionUID = 1L;
 
     protected final byte[] packet;
-
+    
     /**
      * Class constructor.
      * @param packet the packet data to send in the packet-out
      */
+    public PacketOutNotification() {
+    	packet = null;
+    }
+    
     public PacketOutNotification(byte[] packet) {
         this.packet = packet;
     }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
index d235c37..942194b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -2,6 +2,7 @@
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -26,7 +27,14 @@
 import net.onrc.onos.datagrid.IEventChannelListener;
 import net.onrc.onos.ofcontroller.bgproute.Interface;
 import net.onrc.onos.ofcontroller.core.config.IConfigInfoService;
+import net.onrc.onos.ofcontroller.devicemanager.IOnosDeviceService;
 import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
+import net.onrc.onos.ofcontroller.networkgraph.Device;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.Port;
 import net.onrc.onos.ofcontroller.util.SwitchPort;
 import net.onrc.onos.packet.ARP;
 import net.onrc.onos.packet.Ethernet;
@@ -58,91 +66,135 @@
 
     private IFloodlightProviderService floodlightProvider;
     private IDatagridService datagrid;
-    private IEventChannel<PacketOutNotification, PacketOutNotification> packetOutEventChannel;
-    private IEventChannel<ArpReplyNotification, ArpReplyNotification> arpReplyEventChannel;
-    private static final String PACKET_OUT_CHANNEL_NAME = "onos.packet_out";
+    private IEventChannel<Long, ArpReplyNotification> arpReplyEventChannel;
+    private IEventChannel<Long, BroadcastPacketOutNotification> broadcastPacketOutEventChannel;
+    private IEventChannel<Long, SinglePacketOutNotification> singlePacketOutEventChannel;
     private static final String ARP_REPLY_CHANNEL_NAME = "onos.arp_reply";
-    private PacketOutEventHandler packetOutEventHandler =
-	new PacketOutEventHandler();
-    private ArpReplyEventHandler arpReplyEventHandler =
-	new ArpReplyEventHandler();
+    private static final String BROADCAST_PACKET_OUT_CHANNEL_NAME = "onos.broadcast_packet_out";
+    private static final String SINGLE_PACKET_OUT_CHANNEL_NAME = "onos.single_packet_out";
+    private ArpReplyEventHandler arpReplyEventHandler = new ArpReplyEventHandler();
+    private BroadcastPacketOutEventHandler broadcastPacketOutEventHandler = new BroadcastPacketOutEventHandler();  
+    private SinglePacketOutEventHandler singlePacketOutEventHandler = new SinglePacketOutEventHandler();
 
     private IConfigInfoService configService;
     private IRestApiService restApi;
     private IFlowPusherService flowPusher;
+    
+	private INetworkGraphService networkGraphService;
+	private NetworkGraph networkGraph;
+	private IOnosDeviceService onosDeviceService;
 
     private short vlan;
     private static final short NO_VLAN = 0;
 
     private SetMultimap<InetAddress, ArpRequest> arpRequests;
 
-    //
-    // TODO: Using PacketOutNotification as both the key and the
-    // value is a hack that should be removed when this module is
-    // refactored.
-    //
-    private class PacketOutEventHandler implements
-	IEventChannelListener<PacketOutNotification, PacketOutNotification> {
-	@Override
-	public void entryAdded(PacketOutNotification packetOutNotification) {
-	    if (packetOutNotification instanceof SinglePacketOutNotification) {
-		SinglePacketOutNotification notification =
-		    (SinglePacketOutNotification) packetOutNotification;
-		sendArpRequestOutPort(notification.packet,
-				      notification.getOutSwitch(),
-				      notification.getOutPort());
+    private class BroadcastPacketOutEventHandler implements
+    IEventChannelListener<Long, BroadcastPacketOutNotification> {
 
-		// set timestamp
-		InetAddress addr = notification.getTargetAddress();
-		if (addr != null) {
-		    for (ArpRequest request : arpRequests.get(addr)) {
-			request.setRequestTime();
-		    }
+		@Override
+		public void entryAdded(BroadcastPacketOutNotification value) {
+			if(log.isTraceEnabled()) {
+				log.trace("entryAdded ip{}, sw {}, port {}, packet {}", value.getTargetAddress(), value.getInSwitch(), value.getInPort(), value.packet.length);
+			}
+			BroadcastPacketOutNotification notification = (BroadcastPacketOutNotification) value;
+			broadcastArpRequestOutMyEdge(notification.packet,
+						     notification.getInSwitch(),
+						     notification.getInPort());
+		
+			// set timestamp
+			ByteBuffer buffer = ByteBuffer.allocate(4);
+			buffer.putInt(notification.getTargetAddress());
+			InetAddress addr = null;
+			try {
+				addr = InetAddress.getByAddress(buffer.array());
+			} catch (UnknownHostException e) {
+				log.error("Exception:", e);
+			}
+			
+			if (addr != null) {
+			    for (ArpRequest request : arpRequests.get(addr)) {
+			    	request.setRequestTime();
+			    }
+			}			
 		}
-	    } else if (packetOutNotification instanceof BroadcastPacketOutNotification) {
-		BroadcastPacketOutNotification notification =
-		    (BroadcastPacketOutNotification) packetOutNotification;
-		broadcastArpRequestOutMyEdge(notification.packet,
-					     notification.getInSwitch(),
-					     notification.getInPort());
-
-		// set timestamp
-		InetAddress addr = notification.getTargetAddress();
-		if (addr != null) {
-		    for (ArpRequest request : arpRequests.get(addr)) {
-			request.setRequestTime();
-		    }
+		
+		@Override
+		public void entryUpdated(BroadcastPacketOutNotification value) {
+			log.debug("entryUpdated");
+		    // TODO: For now, entryUpdated() is processed as entryAdded()
+		    entryAdded(value);
 		}
-	    } else {
-		log.warn("Unknown packet out notification received");
-	    }
-	}
-
-	@Override
-	public void entryUpdated(PacketOutNotification packetOutNotification) {
-	    // TODO: For now, entryUpdated() is processed as entryAdded()
-	    entryAdded(packetOutNotification);
-	}
-
-	@Override
-	public void entryRemoved(PacketOutNotification packetOutNotification) {
-	    // TODO: Not implemented. Revisit when this module is refactored
-	}
+		
+		@Override
+		public void entryRemoved(BroadcastPacketOutNotification value) {
+			log.debug("entryRemoved");
+		    // TODO: Not implemented. Revisit when this module is refactored
+		}
+    }
+    
+    private class SinglePacketOutEventHandler implements
+		IEventChannelListener<Long, SinglePacketOutNotification> {
+		@Override
+		public void entryAdded(SinglePacketOutNotification packetOutNotification) {
+			log.debug("entryAdded");
+			SinglePacketOutNotification notification =
+			    (SinglePacketOutNotification) packetOutNotification;
+			sendArpRequestOutPort(notification.packet,
+					      notification.getOutSwitch(),
+					      notification.getOutPort());
+	
+			// set timestamp
+			ByteBuffer buffer = ByteBuffer.allocate(4);
+			buffer.putInt(notification.getTargetAddress());
+			InetAddress addr = null;
+			try {
+				addr = InetAddress.getByAddress(buffer.array());
+			} catch (UnknownHostException e) {
+				log.error("Exception:", e);
+			}
+			
+			if (addr != null) {
+			    for (ArpRequest request : arpRequests.get(addr)) {
+			    	request.setRequestTime();
+			    }
+			}		
+		}
+	
+		@Override
+		public void entryUpdated(SinglePacketOutNotification packetOutNotification) {
+			log.debug("entryUpdated");
+		    // TODO: For now, entryUpdated() is processed as entryAdded()
+		    entryAdded(packetOutNotification);
+		}
+	
+		@Override
+		public void entryRemoved(SinglePacketOutNotification packetOutNotification) {
+			log.debug("entryRemoved");
+		    // TODO: Not implemented. Revisit when this module is refactored
+		}
     }
 
-    //
-    // TODO: Using ArpReplyNotification as both the key and the
-    // value is a hack that should be removed when this module is
-    // refactored.
-    //
     private class ArpReplyEventHandler implements
-	IEventChannelListener<ArpReplyNotification, ArpReplyNotification> {
+	IEventChannelListener<Long, ArpReplyNotification> {
+    	
 	@Override
 	public void entryAdded(ArpReplyNotification arpReply) {
-	    log.debug("Received ARP reply notification for {}",
-		      arpReply.getTargetAddress());
-	    sendArpReplyToWaitingRequesters(arpReply.getTargetAddress(),
-					    arpReply.getTargetMacAddress());
+	    log.debug("Received ARP reply notification for ip {}, mac {}",
+	    		arpReply.getTargetAddress(), arpReply.getTargetMacAddress());
+		ByteBuffer buffer = ByteBuffer.allocate(4);
+		buffer.putInt(arpReply.getTargetAddress());
+		InetAddress addr = null;
+		try {
+			addr = InetAddress.getByAddress(buffer.array());
+		} catch (UnknownHostException e) {
+			log.error("Exception:", e);
+		}
+	   
+		if(addr != null) {
+			sendArpReplyToWaitingRequesters(addr,
+				    arpReply.getTargetMacAddress());
+		}
 	}
 
 	@Override
@@ -209,6 +261,10 @@
             ProxyArpManager.this.sendArpReply(arpRequest, dpid, port,
                     macAddress);
         }
+        
+		public ARP getArpRequest() {
+			return arpRequest;
+		}
     }
 
     @Override
@@ -236,17 +292,20 @@
         dependencies.add(IDatagridService.class);
         dependencies.add(IConfigInfoService.class);
         dependencies.add(IFlowPusherService.class);
+        dependencies.add(INetworkGraphService.class);
+        dependencies.add(IOnosDeviceService.class);
         return dependencies;
     }
 
     @Override
     public void init(FloodlightModuleContext context) {
-        this.floodlightProvider = context
-                .getServiceImpl(IFloodlightProviderService.class);
-        this.datagrid = context.getServiceImpl(IDatagridService.class);
+        this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); 
         this.configService = context.getServiceImpl(IConfigInfoService.class);
         this.restApi = context.getServiceImpl(IRestApiService.class);
+        this.datagrid = context.getServiceImpl(IDatagridService.class);
         this.flowPusher = context.getServiceImpl(IFlowPusherService.class);
+        this.networkGraphService = context.getServiceImpl(INetworkGraphService.class);
+        this.onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
 
         // arpCache = new ArpCache();
 
@@ -262,22 +321,24 @@
 
         restApi.addRestletRoutable(new ArpWebRoutable());
         floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-
+		networkGraph = networkGraphService.getNetworkGraph();
+		
 	//
 	// Event notification setup: channels and event handlers
-	//
-	//
-	// TODO: Using PacketOutNotification or ArpReplyNotification as both
-	// the key and the value is a hack that should be removed when this
-	// module is refactored.
-	//
-	packetOutEventChannel = datagrid.addListener(PACKET_OUT_CHANNEL_NAME,
-						     packetOutEventHandler,
-						     PacketOutNotification.class,
-						     PacketOutNotification.class);
+	//	
+	broadcastPacketOutEventChannel = datagrid.addListener(BROADCAST_PACKET_OUT_CHANNEL_NAME,
+			     broadcastPacketOutEventHandler,
+			     Long.class,
+			     BroadcastPacketOutNotification.class);
+	
+	singlePacketOutEventChannel = datagrid.addListener(SINGLE_PACKET_OUT_CHANNEL_NAME,
+			     singlePacketOutEventHandler,
+			     Long.class,
+			     SinglePacketOutNotification.class);
+	
 	arpReplyEventChannel = datagrid.addListener(ARP_REPLY_CHANNEL_NAME,
 						    arpReplyEventHandler,
-						    ArpReplyNotification.class,
+						    Long.class,
 						    ArpReplyNotification.class);
 
         Timer arpTimer = new Timer("arp-processing");
@@ -313,19 +374,17 @@
                     log.debug("Cleaning expired ARP request for {}", entry
                             .getKey().getHostAddress());
 
-                    // If the ARP request is expired and then delete the device
-                    // TODO check whether this is OK from this thread
-                    // TODO: Fix the code below after deviceStorage was removed
-                    /*
-                    IDeviceObject targetDevice =
-                    		deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(entry.getKey()));
-                    if (targetDevice != null) {
-                    	deviceStorage.removeDevice(targetDevice);
-                    	if (log.isDebugEnabled()) {
-                    		log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDevice);
-                    	}
-                    }
-                    */
+					// If the ARP request is expired and then delete the device
+					// TODO check whether this is OK from this thread
+					HostArpRequester requester = (HostArpRequester) request.requester;
+					ARP req = requester.getArpRequest();
+					Device targetDev = networkGraph.getDeviceByMac(MACAddress.valueOf(req.getTargetHardwareAddress()));
+					if(targetDev != null) {
+						onosDeviceService.deleteOnosDeviceByMac(MACAddress.valueOf(req.getTargetHardwareAddress()));
+						if (log.isDebugEnabled()) {
+							log.debug("RemoveDevice: {} due to no have not recieve the ARP reply", targetDev.getMacAddress());
+						}
+					}
 
                     it.remove();
 
@@ -434,90 +493,79 @@
 
         // MACAddress macAddress = arpCache.lookup(target);
 
-        arpRequests.put(
-                target,
-                new ArpRequest(new HostArpRequester(arp, sw.getId(), pi
-                        .getInPort()), false));
+		arpRequests.put(target, new ArpRequest(
+				new HostArpRequester(arp, sw.getId(), pi.getInPort()), false));
+		
+		Device targetDevice = networkGraph.getDeviceByMac(MACAddress.valueOf(arp.getTargetHardwareAddress()));
 
-        // TODO: Fix the code below after deviceStorage was removed
-        /*
-        IDeviceObject targetDevice =
-        		deviceStorage.getDeviceByIP(InetAddresses.coerceToInteger(target));
-        */
+		if (targetDevice == null) {
+			if (log.isTraceEnabled()) {
+				log.trace("No device info found for {} - broadcasting",
+						target.getHostAddress());
+			}
+			
+			// We don't know the device so broadcast the request out
+			BroadcastPacketOutNotification key =
+					new BroadcastPacketOutNotification(eth.serialize(),
+							ByteBuffer.wrap(arp.getTargetProtocolAddress()).getInt(), sw.getId(), pi.getInPort());
+			log.debug("broadcastPacketOutEventChannel mac {}, ip {}, dpid {}, port {}, paket {}", eth.getSourceMAC().toLong(), 
+					ByteBuffer.wrap(arp.getTargetProtocolAddress()).getInt(), sw.getId(), pi.getInPort(), eth.serialize().length);
+			broadcastPacketOutEventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
+		}
+		else {
+			// Even if the device exists in our database, we do not reply to
+			// the request directly, but check whether the device is still valid
+			MACAddress macAddress = MACAddress.valueOf(arp.getTargetHardwareAddress());
 
-        // TODO: Fix the code below after deviceStorage was removed
-        /*
-        if (targetDevice == null) {
-        	if (log.isTraceEnabled()) {
-        		log.trace("No device info found for {} - broadcasting",
-        				target.getHostAddress());
-        	}
+			if (log.isTraceEnabled()) {
+				log.trace("The target Device Record in DB is: {} => {} from ARP request host at {}/{}",
+						new Object [] {
+						inetAddressToString(arp.getTargetProtocolAddress()),
+						macAddress,
+						HexString.toHexString(sw.getId()), pi.getInPort()});
+			}
 
-        	// We don't know the device so broadcast the request out
-		PacketOutNotification key =
-		    new BroadcastPacketOutNotification(eth.serialize(),
-        					target, sw.getId(),
-						pi.getInPort());
-        	packetOutEventChannel.addTransientEntry(key, key);
-        }
-        else {
-        	// Even if the device exists in our database, we do not reply to
-        	// the request directly, but check whether the device is still valid
-        	MACAddress macAddress = MACAddress.valueOf(targetDevice.getMACAddress());
+			// sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
 
-        	if (log.isTraceEnabled()) {
-        		log.trace("The target Device Record in DB is: {} => {} from ARP request host at {}/{}",
-        				new Object [] {
-        				inetAddressToString(arp.getTargetProtocolAddress()),
-        				macAddress,
-        				HexString.toHexString(sw.getId()), pi.getInPort()});
-        	}
+			Iterable<net.onrc.onos.ofcontroller.networkgraph.Port> outPorts = targetDevice.getAttachmentPoints();
 
-        	// sendArpReply(arp, sw.getId(), pi.getInPort(), macAddress);
+			if (!outPorts.iterator().hasNext()){
+				if (log.isTraceEnabled()) {
+					log.trace("Device {} exists but is not connected to any ports" + 
+							" - broadcasting", macAddress);
+				}
+				
+//				BroadcastPacketOutNotification key =
+//						new BroadcastPacketOutNotification(eth.serialize(), 
+//								target, sw.getId(), pi.getInPort());
+//				broadcastPacketOutEventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
+			} 
+			else {
+				for (net.onrc.onos.ofcontroller.networkgraph.Port portObject : outPorts) {
+					//long outSwitch = 0;
+					//short outPort = 0;
 
-        	Iterable<IPortObject> outPorts = targetDevice.getAttachedPorts();
-
-        	if (!outPorts.iterator().hasNext()){
-        		if (log.isTraceEnabled()) {
-        			log.trace("Device {} exists but is not connected to any ports" +
-        					" - broadcasting", macAddress);
-        		}
-			PacketOutNotification key =
-			    new BroadcastPacketOutNotification(eth.serialize(),
-					target, sw.getId(),
-					pi.getInPort());
-			packetOutEventChannel.addTransientEntry(key, key);
-        	}
-        	else {
-        		for (IPortObject portObject : outPorts) {
-        			//long outSwitch = 0;
-        			//short outPort = 0;
-
-        			// if (!portObject.getLinkedPorts().iterator().hasNext()) {
-        			//	outPort = portObject.getNumber();
-        			// }
-        			if (portObject.getLinkedPorts().iterator().hasNext()) {
-        				continue;
-        			}
-
-        			short outPort = portObject.getNumber();
-        			ISwitchObject outSwitchObject = portObject.getSwitch();
-        			long outSwitch = HexString.toLong(outSwitchObject.getDPID());
-
-        			if (log.isTraceEnabled()) {
-        				log.trace("Probing device {} on port {}/{}",
-        						new Object[] {macAddress,
-        						HexString.toHexString(outSwitch), outPort});
-        			}
-
-				PacketOutNotification key =
-        				new SinglePacketOutNotification(eth.serialize(),
-						target, outSwitch, outPort);
-				packetOutEventChannel.addTransientEntry(key, key);
-        		}
-        	}
-        }
-        */
+					if(portObject.getOutgoingLink() != null || portObject.getIncomingLink() != null) {
+						continue;
+					}
+					
+					short outPort = portObject.getNumber().shortValue();
+					Switch outSwitchObject = portObject.getSwitch();
+					long outSwitch = outSwitchObject.getDpid();
+					
+					if (log.isTraceEnabled()) {
+						log.trace("Probing device {} on port {}/{}", 
+								new Object[] {macAddress, 
+								HexString.toHexString(outSwitch), outPort});
+					}
+					
+					SinglePacketOutNotification key =
+						    new SinglePacketOutNotification(eth.serialize(), 
+						    		ByteBuffer.wrap(target.getAddress()).getInt(), outSwitch, outPort);
+					singlePacketOutEventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
+				}
+			}
+		}
     }
 
     // Not used because device manager currently updates the database
@@ -613,16 +661,15 @@
         }
 
         // sendArpRequestToSwitches(ipAddress, eth.serialize());
-	PacketOutNotification key =
-	    new SinglePacketOutNotification(eth.serialize(), ipAddress,
-					    intf.getDpid(), intf.getPort());
-	packetOutEventChannel.addTransientEntry(key, key);
+		SinglePacketOutNotification key =
+		    new SinglePacketOutNotification(eth.serialize(), ByteBuffer.wrap(ipAddress.getAddress()).getInt(),
+						    intf.getDpid(), intf.getPort());
+		singlePacketOutEventChannel.addTransientEntry(MACAddress.valueOf(senderMacAddress).toLong(), key);
     }
-
-    private void sendArpRequestToSwitches(InetAddress dstAddress,
-            byte[] arpRequest) {
-        sendArpRequestToSwitches(dstAddress, arpRequest, 0,
-                OFPort.OFPP_NONE.getValue());
+    
+    private void sendArpRequestToSwitches(InetAddress dstAddress, byte[] arpRequest) {
+    		sendArpRequestToSwitches(dstAddress, arpRequest, 0,
+    		OFPort.OFPP_NONE.getValue());
     }
 
     private void sendArpRequestToSwitches(InetAddress dstAddress,
@@ -672,9 +719,10 @@
 
         MACAddress mac = new MACAddress(arp.getSenderHardwareAddress());
 
-	ArpReplyNotification key =
-	    new ArpReplyNotification(targetAddress, mac);
-	arpReplyEventChannel.addTransientEntry(key, key);
+		ArpReplyNotification key =
+		    new ArpReplyNotification(ByteBuffer.wrap(targetAddress.getAddress()).getInt(), mac);
+		log.debug("ArpReplyNotification ip {}, mac{}", ByteBuffer.wrap(targetAddress.getAddress()).getInt(), mac);
+		arpReplyEventChannel.addTransientEntry(mac.toLong(), key);
     }
 
     private void broadcastArpRequestOutMyEdge(byte[] arpRequest, long inSwitch,
@@ -689,30 +737,27 @@
 
             List<OFAction> actions = new ArrayList<OFAction>();
 
-            // TODO: Fix the code below after topoSwitchService was removed
-            /*
-            Iterable<IPortObject> ports
-            	= topoSwitchService.getPortsOnSwitch(sw.getStringId());
-            if (ports == null) {
-            	continue;
-            }
-
-            for (IPortObject portObject : ports) {
-            	if (!portObject.getLinkedPorts().iterator().hasNext()) {
-            		short portNumber = portObject.getNumber();
-
-            		if (sw.getId() == inSwitch && portNumber == inPort) {
-            			// This is the port that the ARP message came in,
-            			// so don't broadcast out this port
-            			continue;
-            		}
-
-            		switchPorts.add(new SwitchPort(new Dpid(sw.getId()),
-            				new Port(portNumber)));
-            		actions.add(new OFActionOutput(portNumber));
-            	}
-            }
-            */
+			Switch graphSw = networkGraph.getSwitch(sw.getId());
+			Collection<net.onrc.onos.ofcontroller.networkgraph.Port> ports = graphSw.getPorts();
+			
+			if (ports == null) {
+				continue;
+			}
+			
+			for (net.onrc.onos.ofcontroller.networkgraph.Port portObject : ports) {
+				if (portObject.getOutgoingLink() == null && portObject.getNumber() > 0) {
+					Long portNumber = portObject.getNumber();
+					
+					if (sw.getId() == inSwitch && portNumber.shortValue() == inPort) {
+						// This is the port that the ARP message came in,
+						// so don't broadcast out this port
+						continue;
+					}		
+					switchPorts.add(new SwitchPort(new Dpid(sw.getId()), 
+							new net.onrc.onos.ofcontroller.util.Port(portNumber.shortValue())));
+					actions.add(new OFActionOutput(portNumber.shortValue()));
+				}
+			}
 
             po.setActions(actions);
             short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
@@ -853,31 +898,6 @@
         return new ArrayList<String>();
     }
 
-    /*
-    @Override
-    public void arpRequestNotification(ArpMessage arpMessage) {
-    	log.debug("Received ARP notification from other instances");
-
-    	switch (arpMessage.getType()){
-    	case REQUEST:
-    		if(arpMessage.getOutSwitch() == -1 || arpMessage.getOutPort() == -1){
-    			broadcastArpRequestOutMyEdge(arpMessage.getPacket(),
-    					arpMessage.getInSwitch(), arpMessage.getInPort());
-    		}else{
-    			sendArpRequestOutPort(arpMessage.getPacket(),arpMessage.getOutSwitch(),arpMessage.getOutPort());
-    			log.debug("OutSwitch in ARP request message is: {}; " +
-    			"OutPort in ARP request message is: {}",arpMessage.getOutSwitch(),arpMessage.getOutPort());
-    		}
-    		break;
-    	case REPLY:
-    		log.debug("Received ARP reply notification for {}",
-    				arpMessage.getAddress());
-    		sendArpReplyToWaitingRequesters(arpMessage.getAddress(),arpMessage.getMAC());
-    		break;
-    	}
-    }
-    */
-
     private void sendArpReplyToWaitingRequesters(InetAddress address,
             MACAddress mac) {
         log.debug("Sending ARP reply for {} to requesters",
@@ -899,6 +919,7 @@
             }
         }
 
+        //TODO here, comment outed from long time ago. I will check if we need it later.
         /*IDeviceObject deviceObject = deviceStorage.getDeviceByIP(
         		InetAddresses.coerceToInteger(address));
 
@@ -912,4 +933,4 @@
             request.dispatchReply(address, mac);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java
index ab9a9b5..62d8086 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/SinglePacketOutNotification.java
@@ -1,6 +1,6 @@
 package net.onrc.onos.ofcontroller.proxyarp;
 
-import java.net.InetAddress;
+
 
 // TODO This class is too generic to be handled by ProxyArpService.
 /**
@@ -10,7 +10,7 @@
 
     private static final long serialVersionUID = 1L;
 
-    private final InetAddress address;
+    private final int address;
     private final long outSwitch;
     private final short outPort;
 
@@ -21,7 +21,7 @@
      * @param outSwitch the dpid of the switch to send the packet on
      * @param outPort the port number of the port to send the packet out
      */
-    public SinglePacketOutNotification(byte[] packet, InetAddress address,
+    public SinglePacketOutNotification(byte[] packet, int address,
             long outSwitch, short outPort) {
         super(packet);
 
@@ -51,7 +51,7 @@
      * @return the target IP address for ARP packets, or null if the packet is
      *         not an ARP packet
      */
-    public InetAddress getTargetAddress() {
+    public int getTargetAddress() {
         return address;
     }
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java
index 42a3a4d..9425b7e 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java
@@ -3,7 +3,9 @@
 import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashSet;
+
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.intent.ConstrainedShortestPathIntent;
 import net.onrc.onos.intent.ErrorIntent;
@@ -13,12 +15,17 @@
 import net.onrc.onos.intent.PathIntent;
 import net.onrc.onos.intent.ShortestPathIntent;
 import net.onrc.onos.intent.runtime.IntentStateList;
+import net.onrc.onos.ofcontroller.devicemanager.OnosDevice;
 import net.onrc.onos.ofcontroller.networkgraph.DeviceEvent;
 import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
 import net.onrc.onos.ofcontroller.networkgraph.Path;
 import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
 import net.onrc.onos.ofcontroller.networkgraph.SwitchEvent;
 import net.onrc.onos.ofcontroller.networkgraph.TopologyEvent;
+import net.onrc.onos.ofcontroller.proxyarp.ArpReplyNotification;
+import net.onrc.onos.ofcontroller.proxyarp.BroadcastPacketOutNotification;
+import net.onrc.onos.ofcontroller.proxyarp.PacketOutNotification;
+import net.onrc.onos.ofcontroller.proxyarp.SinglePacketOutNotification;
 import net.onrc.onos.ofcontroller.util.CallerId;
 import net.onrc.onos.ofcontroller.util.DataPath;
 import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
@@ -47,6 +54,12 @@
 
 
 
+
+
+
+
+
+
 import com.esotericsoftware.kryo.Kryo;
 
 /**
@@ -208,6 +221,13 @@
 	// Device-related classes
 	kryo.register(HashSet.class);
 	kryo.register(Inet4Address.class);
+	kryo.register(OnosDevice.class);
+	kryo.register(Date.class);
+
+	// ProxyArp-related classes
+	kryo.register(BroadcastPacketOutNotification.class);
+	kryo.register(SinglePacketOutNotification.class);
+	kryo.register(ArpReplyNotification.class);
 
 	return kryo;
     }