Fix checkstyle whitespace issues - WHITESPACE ONLY

Change-Id: Ic205c1afd639c6008d61d9de95cb764eeb6238ca
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
index bdafdcd..2ed8ba5 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
@@ -62,529 +62,526 @@
 import com.google.common.collect.ListMultimap;
 
 public class Forwarding implements IOFMessageListener, IFloodlightModule,
-									IForwardingService, IEventChannelListener<Long, IntentStateList> {
-	private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
-   
-	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 String callerId = "Forwarding";
-	
-	private IFloodlightProviderService floodlightProvider;
-	private IFlowPusherService flowPusher;
-	private IDatagridService datagrid;
+        IForwardingService, IEventChannelListener<Long, IntentStateList> {
+    private final static Logger log = LoggerFactory.getLogger(Forwarding.class);
 
-	private IEventChannel<Long, BroadcastPacketOutNotification> eventChannel;
-	private static final String SINGLE_PACKET_OUT_CHANNEL_NAME = "onos.forwarding.packet_out";
+    private final int SLEEP_TIME_FOR_DB_DEVICE_INSTALLED = 100; // milliseconds
+    private final static int NUMBER_OF_THREAD_FOR_EXECUTOR = 1;
 
-	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<String, PacketToPush> waitingPackets;
-	
-	private final Object lock = new Object();
-	
-	private class PacketToPush {
-		public final OFPacketOut packet;
-		public final long dpid;
-		
-		public PacketToPush(OFPacketOut packet, long dpid) {
-			this.packet = packet;
-			this.dpid = dpid;
-		}
-	}
-	
-	private class PushedFlow {
-		public final String intentId;
-		public boolean installed = false;
-		public short firstOutPort;
-		
-		public PushedFlow(String flowId) {
-			this.intentId = flowId;
-		}
-	}
-	
-	private final class Path {
-		public final MACAddress srcMac;
-		public final MACAddress dstMac;
-		
-		public Path(MACAddress srcMac, MACAddress dstMac) {
-			this.srcMac = srcMac;
-			this.dstMac = dstMac;
-		}
-		
-		@Override
-		public boolean equals(Object other) {
-			if (!(other instanceof Path)) {
-				return false;
-			}
-			
-			Path otherPath = (Path) other;
-			return srcMac.equals(otherPath.srcMac) &&
-					dstMac.equals(otherPath.dstMac);
-		}
-		
-		@Override
-		public int hashCode() {
-			int hash = 17;
-			hash = 31 * hash + srcMac.hashCode();
-			hash = 31 * hash + dstMac.hashCode();
-			return hash;
-		}
-		
-		@Override
-		public String toString() {
-			return "(" + srcMac + ") => (" + dstMac + ")";
-		}
-	}
-	
-	@Override
-	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-		List<Class<? extends IFloodlightService>> services = 
-				new ArrayList<Class<? extends IFloodlightService>>(1);
-		services.add(IForwardingService.class);
-		return services;
-	}
+    private final static ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUMBER_OF_THREAD_FOR_EXECUTOR);
 
-	@Override
-	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
-		Map<Class<? extends IFloodlightService>, IFloodlightService> impls = 
-				new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(1);
-		impls.put(IForwardingService.class, this);
-		return impls;
-	}
+    private final String callerId = "Forwarding";
 
-	@Override
-	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
-		List<Class<? extends IFloodlightService>> dependencies = 
-				new ArrayList<Class<? extends IFloodlightService>>();
-		dependencies.add(IFloodlightProviderService.class);
-		dependencies.add(IFlowPusherService.class);
-		dependencies.add(IControllerRegistryService.class);	
-		dependencies.add(IOnosDeviceService.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);
-		return dependencies;
-	}
-	
-	@Override
-	public void init(FloodlightModuleContext context) {
-		floodlightProvider = 
-				context.getServiceImpl(IFloodlightProviderService.class);
-		flowPusher = context.getServiceImpl(IFlowPusherService.class);
-		datagrid = context.getServiceImpl(IDatagridService.class);
-		controllerRegistryService = context.getServiceImpl(IControllerRegistryService.class);
-		networkGraphService = context.getServiceImpl(INetworkGraphService.class);
+    private IFloodlightProviderService floodlightProvider;
+    private IFlowPusherService flowPusher;
+    private IDatagridService datagrid;
+
+    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<String, PacketToPush> waitingPackets;
+
+    private final Object lock = new Object();
+
+    private class PacketToPush {
+        public final OFPacketOut packet;
+        public final long dpid;
+
+        public PacketToPush(OFPacketOut packet, long dpid) {
+            this.packet = packet;
+            this.dpid = dpid;
+        }
+    }
+
+    private class PushedFlow {
+        public final String intentId;
+        public boolean installed = false;
+        public short firstOutPort;
+
+        public PushedFlow(String flowId) {
+            this.intentId = flowId;
+        }
+    }
+
+    private final class Path {
+        public final MACAddress srcMac;
+        public final MACAddress dstMac;
+
+        public Path(MACAddress srcMac, MACAddress dstMac) {
+            this.srcMac = srcMac;
+            this.dstMac = dstMac;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (!(other instanceof Path)) {
+                return false;
+            }
+
+            Path otherPath = (Path) other;
+            return srcMac.equals(otherPath.srcMac) &&
+                    dstMac.equals(otherPath.dstMac);
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 17;
+            hash = 31 * hash + srcMac.hashCode();
+            hash = 31 * hash + dstMac.hashCode();
+            return hash;
+        }
+
+        @Override
+        public String toString() {
+            return "(" + srcMac + ") => (" + dstMac + ")";
+        }
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+        List<Class<? extends IFloodlightService>> services =
+                new ArrayList<Class<? extends IFloodlightService>>(1);
+        services.add(IForwardingService.class);
+        return services;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+        Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
+                new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(1);
+        impls.put(IForwardingService.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(IFlowPusherService.class);
+        dependencies.add(IControllerRegistryService.class);
+        dependencies.add(IOnosDeviceService.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);
+        return dependencies;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context) {
+        floodlightProvider =
+                context.getServiceImpl(IFloodlightProviderService.class);
+        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);
 
-		pendingFlows = new HashMap<Path, PushedFlow>();
-		waitingPackets = LinkedListMultimap.create();
-	}
-	
-	@Override
-	public void startUp(FloodlightModuleContext context) {
+        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
 
-		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);
-	}
+        pendingFlows = new HashMap<Path, PushedFlow>();
+        waitingPackets = LinkedListMultimap.create();
+    }
 
-	@Override
-	public String getName() {
-		return "onosforwarding";
-	}
+    @Override
+    public void startUp(FloodlightModuleContext context) {
 
-	@Override
-	public boolean isCallbackOrderingPrereq(OFType type, String name) {
-		return (type == OFType.PACKET_IN) && 
-				(name.equals("devicemanager") || name.equals("proxyarpmanager")
-				|| name.equals("onosdevicemanager"));
-	}
+        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
-	public boolean isCallbackOrderingPostreq(OFType type, String name) {
-		return false;
-	}
+    @Override
+    public String getName() {
+        return "onosforwarding";
+    }
 
-	@Override
-	public Command receive(
-			IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-		
-		if (msg.getType() != OFType.PACKET_IN) {
-			return Command.CONTINUE;
-		}
-		
-		OFPacketIn pi = (OFPacketIn) msg;
-		
-		Ethernet eth = IFloodlightProviderService.bcStore.
-				get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-		
-		log.debug("Receive PACKET_IN swId {}, portId {}", sw.getId(), pi.getInPort());
-		
-		if (eth.getEtherType() != Ethernet.TYPE_IPv4) {
-			return Command.CONTINUE;
-		}
-		
-		if (eth.isBroadcast() || eth.isMulticast()) {
-			handleBroadcast(sw, pi, eth);
-		}
-		else {
-			// Unicast
-			handlePacketIn(sw, pi, eth);
-		}
-		
-		return Command.STOP;
-	}
-	
-	private void handleBroadcast(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
-		if (log.isTraceEnabled()) {
-			log.trace("Sending broadcast packet to other ONOS instances");
-		}
+    @Override
+    public boolean isCallbackOrderingPrereq(OFType type, String name) {
+        return (type == OFType.PACKET_IN) &&
+                (name.equals("devicemanager") || name.equals("proxyarpmanager")
+                        || name.equals("onosdevicemanager"));
+    }
 
-		//We don't use address information, so 0 is put into the third argument.
-		BroadcastPacketOutNotification key =
-		    new BroadcastPacketOutNotification(
-						       eth.serialize(),
-						       0, sw.getId(),
-						       pi.getInPort());
-		eventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
-	}
-	
-	private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth){
-		log.debug("Start handlePacketIn swId {}, portId {}", sw.getId(), pi.getInPort());
+    @Override
+    public boolean isCallbackOrderingPostreq(OFType type, String name) {
+        return false;
+    }
 
-		String destinationMac = 
-				HexString.toHexString(eth.getDestinationMACAddress()); 
-		
-		//FIXME getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
-		Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(destinationMac));
+    @Override
+    public Command receive(
+            IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
 
-		if (deviceObject == null) {
-			log.debug("No device entry found for {}",
-					destinationMac);
+        if (msg.getType() != OFType.PACKET_IN) {
+            return Command.CONTINUE;
+        }
 
-			//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;
-		}
+        OFPacketIn pi = (OFPacketIn) msg;
 
-		continueHandlePacketIn(sw, pi, eth, deviceObject);
-	}
-	
-	private class WaitDeviceArp implements Runnable {
-		IOFSwitch sw;
-		OFPacketIn pi;
-		Ethernet eth;
+        Ethernet eth = IFloodlightProviderService.bcStore.
+                get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
 
-		public WaitDeviceArp(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
-			super();
-			this.sw = sw;
-			this.pi = pi;
-			this.eth = eth;
-		}
+        log.debug("Receive PACKET_IN swId {}, portId {}", sw.getId(), pi.getInPort());
 
-		@Override
-		public void run() {
-			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);
-		}
-	}
+        if (eth.getEtherType() != Ethernet.TYPE_IPv4) {
+            return Command.CONTINUE;
+        }
 
-	private void continueHandlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth, Device deviceObject) {
+        if (eth.isBroadcast() || eth.isMulticast()) {
+            handleBroadcast(sw, pi, eth);
+        } else {
+            // Unicast
+            handlePacketIn(sw, pi, eth);
+        }
 
-		log.debug("Start continuehandlePacketIn");
-		
-		//Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();	
-		Iterator<net.onrc.onos.core.topology.Port> ports = deviceObject.getAttachmentPoints().iterator();	
-		if (!ports.hasNext()) {
-			log.debug("No attachment point found for device {} - broadcasting packet", 
-					deviceObject.getMacAddress());
-			handleBroadcast(sw, pi, eth);
-			return;	
-		}
+        return Command.STOP;
+    }
 
-		//This code assumes the device has only one port. It should be problem.
-		net.onrc.onos.core.topology.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(
-				new Dpid(sw.getId()), new Port(pi.getInPort())); 
-		SwitchPort dstSwitchPort = new SwitchPort(
-				new Dpid(destinationDpid), new Port(destinationPort)); 
-				
-		MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
-		MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
-		
-		synchronized (lock) {
-			//TODO check concurrency
-			Path pathspec = new Path(srcMacAddress, dstMacAddress);	
-			PushedFlow existingFlow = pendingFlows.get(pathspec);
+    private void handleBroadcast(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+        if (log.isTraceEnabled()) {
+            log.trace("Sending broadcast packet to other ONOS instances");
+        }
 
-			//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 {}, intent ID is {}", 
-							pathspec, 
-							existingFlow.intentId);
-				}
-				
-				OFPacketOut po = constructPacketOut(pi, sw);
-				
-				// Find the correct port here. We just assume the PI is from 
-				// the first hop switch, but this is definitely not always
-				// the case. We'll have to retrieve the flow from HZ every time
-				// because it could change (be rerouted) sometimes.
-				if (existingFlow.installed) {
-					// Flow has been sent to the switches so it is safe to
-					// send a packet out now
+        //We don't use address information, so 0 is put into the third argument.
+        BroadcastPacketOutNotification key =
+                new BroadcastPacketOutNotification(
+                        eth.serialize(),
+                        0, sw.getId(),
+                        pi.getInPort());
+        eventChannel.addTransientEntry(eth.getDestinationMAC().toLong(), key);
+    }
 
-					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;
-					}
-					
-					Boolean isflowEntryForThisSwitch = false;		
-					net.onrc.onos.core.topology.Path path = pathIntent.getPath();
+    private void handlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+        log.debug("Start handlePacketIn swId {}, portId {}", sw.getId(), pi.getInPort());
 
-					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 (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 {}-{}",
-								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 {}", existingFlow.intentId);
-					waitingPackets.put(existingFlow.intentId, new PacketToPush(po, sw.getId()));
-				}
-				return;
-			}
+        String destinationMac =
+                HexString.toHexString(eth.getDestinationMACAddress());
 
-			log.debug("Adding new flow between {} at {} and {} at {}",
-					new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
-			
-			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);
+        //FIXME getDeviceByMac() is a blocking call, so it may be better way to handle it to avoid the condition.
+        Device deviceObject = networkGraph.getDeviceByMac(MACAddress.valueOf(destinationMac));
 
-			OFPacketOut po = constructPacketOut(pi, sw);
-			
-			// Add to waiting lists
-			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);
-			
-		}
-	}
+        if (deviceObject == null) {
+            log.debug("No device entry found for {}",
+                    destinationMac);
 
-	private OFPacketOut constructPacketOut(OFPacketIn pi, IOFSwitch sw) {	
-		OFPacketOut po = new OFPacketOut();
-		po.setInPort(OFPort.OFPP_NONE)
-		.setInPort(pi.getInPort())
-		.setActions(new ArrayList<OFAction>())
-		.setLengthU(OFPacketOut.MINIMUM_LENGTH);
-		
-		if (sw.getBuffers() == 0) {
-			po.setBufferId(OFPacketOut.BUFFER_ID_NONE)
-			.setPacketData(pi.getPacketData())
-			.setLengthU(po.getLengthU() + po.getPacketData().length);
-		}
-		else {
-			po.setBufferId(pi.getBufferId());
-		}
-		
-		return po;
-	}
+            //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;
+        }
 
-	@Override
-	public void flowsInstalled(Collection<FlowPath> installedFlowPaths) {
-	}
-	
-	@Override
-	public void flowRemoved(FlowPath removedFlowPath) {
-	}
-	
-	public void flowRemoved(PathIntent removedIntent) {
-		if(log.isTraceEnabled()){
-			log.trace("Path {} was removed", removedIntent.getParentIntent().getId());
-		}
+        continueHandlePacketIn(sw, pi, eth, deviceObject);
+    }
 
-		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(spfIntent.getId());
-			if (!packets.isEmpty()) {
-				log.warn("Removed flow {} has packets queued.",  spfIntent.getId());
-			}
-			pendingFlows.remove(removedPath);
-			log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, spfIntent.getId());
-		}
-	}
-	
-	private void flowInstalled(PathIntent installedPath) {	
-		if(log.isTraceEnabled()){
-			log.trace("Path {} was installed", installedPath.getParentIntent().getId());
-		}
-		
-		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 = null;
-		net.onrc.onos.core.topology.Path graphPath = installedPath.getPath();
-		
-		log.debug("path{}", graphPath);
-		Short outPort = graphPath.get(0).getSrc().getNumber().shortValue();
-	
-		PushedFlow existingFlow = null;
-		
-		synchronized (lock) {
-			existingFlow = pendingFlows.get(path);
+    private class WaitDeviceArp implements Runnable {
+        IOFSwitch sw;
+        OFPacketIn pi;
+        Ethernet eth;
 
-			if (existingFlow != null) {
-			    existingFlow.installed = true;
-			    existingFlow.firstOutPort = outPort;
-			} else {
-				log.debug("ExistingFlow {} is null", path);
-				return;
-			}
+        public WaitDeviceArp(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
+            super();
+            this.sw = sw;
+            this.pi = pi;
+            this.eth = eth;
+        }
 
-			//Check both existing flow are installed status.
-			if(existingFlow.installed){
-				packets = waitingPackets.removeAll(existingFlow.intentId);
-				if(log.isDebugEnabled()){
-					log.debug("removed my packets {} to push from waitingPackets. outPort {} 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 {}, path {}", packet.dpid, existingFlow.firstOutPort, path);
-			IOFSwitch sw = floodlightProvider.getSwitches().get(packet.dpid);
-			sendPacketOut(sw, packet.packet, existingFlow.firstOutPort);
-		}
-	}
-	
-	private void sendPacketOut(IOFSwitch sw, OFPacketOut po, short outPort) {
-		po.getActions().add(new OFActionOutput(outPort));
-		po.setActionsLength((short)
-				(po.getActionsLength() + OFActionOutput.MINIMUM_LENGTH));
-		po.setLengthU(po.getLengthU() + OFActionOutput.MINIMUM_LENGTH);
-		
-		flowPusher.add(sw, po);
-	}
+        @Override
+        public void run() {
+            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);
+        }
+    }
 
-	@Override
-	public void entryAdded(IntentStateList value) {
-		entryUpdated(value);
-		
-	}
+    private void continueHandlePacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth, Device deviceObject) {
 
-	@Override
-	public void entryRemoved(IntentStateList value) {
-		//no-op
-	}
+        log.debug("Start continuehandlePacketIn");
 
-	@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;
+        //Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
+        Iterator<net.onrc.onos.core.topology.Port> ports = deviceObject.getAttachmentPoints().iterator();
+        if (!ports.hasNext()) {
+            log.debug("No attachment point found for device {} - broadcasting packet",
+                    deviceObject.getMacAddress());
+            handleBroadcast(sw, pi, eth);
+            return;
+        }
 
-			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;
-				}
-		}
-	}
+        //This code assumes the device has only one port. It should be problem.
+        net.onrc.onos.core.topology.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(
+                new Dpid(sw.getId()), new Port(pi.getInPort()));
+        SwitchPort dstSwitchPort = new SwitchPort(
+                new Dpid(destinationDpid), new Port(destinationPort));
+
+        MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
+        MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
+
+        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 {}, intent ID is {}",
+                            pathspec,
+                            existingFlow.intentId);
+                }
+
+                OFPacketOut po = constructPacketOut(pi, sw);
+
+                // Find the correct port here. We just assume the PI is from
+                // the first hop switch, but this is definitely not always
+                // the case. We'll have to retrieve the flow from HZ every time
+                // because it could change (be rerouted) sometimes.
+                if (existingFlow.installed) {
+                    // Flow has been sent to the switches so it is safe to
+                    // send a packet out now
+
+                    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;
+                    }
+
+                    Boolean isflowEntryForThisSwitch = false;
+                    net.onrc.onos.core.topology.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 (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 {}-{}",
+                                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 {}", existingFlow.intentId);
+                    waitingPackets.put(existingFlow.intentId, new PacketToPush(po, sw.getId()));
+                }
+                return;
+            }
+
+            log.debug("Adding new flow between {} at {} and {} at {}",
+                    new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
+
+            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(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);
+
+        }
+    }
+
+    private OFPacketOut constructPacketOut(OFPacketIn pi, IOFSwitch sw) {
+        OFPacketOut po = new OFPacketOut();
+        po.setInPort(OFPort.OFPP_NONE)
+                .setInPort(pi.getInPort())
+                .setActions(new ArrayList<OFAction>())
+                .setLengthU(OFPacketOut.MINIMUM_LENGTH);
+
+        if (sw.getBuffers() == 0) {
+            po.setBufferId(OFPacketOut.BUFFER_ID_NONE)
+                    .setPacketData(pi.getPacketData())
+                    .setLengthU(po.getLengthU() + po.getPacketData().length);
+        } else {
+            po.setBufferId(pi.getBufferId());
+        }
+
+        return po;
+    }
+
+    @Override
+    public void flowsInstalled(Collection<FlowPath> installedFlowPaths) {
+    }
+
+    @Override
+    public void flowRemoved(FlowPath removedFlowPath) {
+    }
+
+    public void flowRemoved(PathIntent removedIntent) {
+        if (log.isTraceEnabled()) {
+            log.trace("Path {} was removed", removedIntent.getParentIntent().getId());
+        }
+
+        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(spfIntent.getId());
+            if (!packets.isEmpty()) {
+                log.warn("Removed flow {} has packets queued.", spfIntent.getId());
+            }
+            pendingFlows.remove(removedPath);
+            log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, spfIntent.getId());
+        }
+    }
+
+    private void flowInstalled(PathIntent installedPath) {
+        if (log.isTraceEnabled()) {
+            log.trace("Path {} was installed", installedPath.getParentIntent().getId());
+        }
+
+        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 = null;
+        net.onrc.onos.core.topology.Path graphPath = installedPath.getPath();
+
+        log.debug("path{}", graphPath);
+        Short outPort = graphPath.get(0).getSrc().getNumber().shortValue();
+
+        PushedFlow existingFlow = null;
+
+        synchronized (lock) {
+            existingFlow = pendingFlows.get(path);
+
+            if (existingFlow != null) {
+                existingFlow.installed = true;
+                existingFlow.firstOutPort = outPort;
+            } else {
+                log.debug("ExistingFlow {} is null", path);
+                return;
+            }
+
+            //Check both existing flow are installed status.
+            if (existingFlow.installed) {
+                packets = waitingPackets.removeAll(existingFlow.intentId);
+                if (log.isDebugEnabled()) {
+                    log.debug("removed my packets {} to push from waitingPackets. outPort {} 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 {}, path {}", packet.dpid, existingFlow.firstOutPort, path);
+            IOFSwitch sw = floodlightProvider.getSwitches().get(packet.dpid);
+            sendPacketOut(sw, packet.packet, existingFlow.firstOutPort);
+        }
+    }
+
+    private void sendPacketOut(IOFSwitch sw, OFPacketOut po, short outPort) {
+        po.getActions().add(new OFActionOutput(outPort));
+        po.setActionsLength((short)
+                (po.getActionsLength() + OFActionOutput.MINIMUM_LENGTH));
+        po.setLengthU(po.getLengthU() + OFActionOutput.MINIMUM_LENGTH);
+
+        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;
+            }
+        }
+    }
 }