diff --git a/src/main/java/net/floodlightcontroller/flowcache/OFMatchReconcile.java b/src/main/java/net/floodlightcontroller/flowcache/OFMatchReconcile.java
index 68831f46eb0ba9181b948aa28ecbc075b6f0fd96..4bbab302e46009fd6b31670f7dd051c5d88abd5f 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/OFMatchReconcile.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/OFMatchReconcile.java
@@ -49,6 +49,8 @@ public class OFMatchReconcile  {
     public String newAppInstName;
     /** The reconcile action. */
     public ReconcileAction rcAction;
+    /** Outport in the event of UPDATE_PATH action**/
+    public short outPort;
 
     // The context for the reconcile action
     public FloodlightContext cntx;
@@ -72,6 +74,7 @@ public class OFMatchReconcile  {
         appInstName = copy.appInstName;
         newAppInstName = copy.newAppInstName;
         rcAction = copy.rcAction;
+        outPort = copy.outPort;
         cntx = new FloodlightContext();
     }
     
@@ -79,6 +82,6 @@ public class OFMatchReconcile  {
     public String toString() {
         return "OFMatchReconcile [" + ofmWithSwDpid + " priority=" + priority + " action=" + action + 
                 " cookie=" + cookie + " appInstName=" + appInstName + " newAppInstName=" + newAppInstName + 
-                " ReconcileAction=" + rcAction + "]";
+                " ReconcileAction=" + rcAction + "outPort=" + outPort + "]";
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/flowcache/PortDownReconciliation.java b/src/main/java/net/floodlightcontroller/flowcache/PortDownReconciliation.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a4275a33c808bcab9e987aa146cbc57725277dc
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/PortDownReconciliation.java
@@ -0,0 +1,499 @@
+/**
+*    Copyright 2012, Jason Parraga, Marist College 
+* 
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+package net.floodlightcontroller.flowcache;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMatchWithSwDpid;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFStatisticsRequest;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.statistics.OFFlowStatisticsReply;
+import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.openflow.protocol.statistics.OFStatisticsType;
+import org.openflow.util.HexString;
+import org.openflow.util.U16;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.flowcache.IFlowReconcileListener;
+import net.floodlightcontroller.flowcache.IFlowReconcileService;
+import net.floodlightcontroller.flowcache.OFMatchReconcile;
+import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
+import net.floodlightcontroller.linkdiscovery.LinkInfo;
+import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
+import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.floodlightcontroller.routing.Link;
+import net.floodlightcontroller.topology.ITopologyListener;
+import net.floodlightcontroller.topology.ITopologyService;
+
+/**
+ * Flow reconciliation module that is triggered by PORT_DOWN events. This module
+ * will recursively trace back all flows from the immediately affected switch
+ * and remove them (specifically flows with an idle timeout that would not be
+ * exhausted). Once the flows are deleted Floodlight will re-evaluate the path
+ * the traffic should take with it's updated topology map.
+ * 
+ * @author Jason Parraga
+ */
+
+public class PortDownReconciliation implements IFloodlightModule,
+		ITopologyListener, IFlowReconcileListener {
+	protected static Logger log = LoggerFactory
+			.getLogger(PortDownReconciliation.class);
+
+	protected ITopologyService topology;
+	protected IFloodlightProviderService floodlightProvider;
+	protected IFlowReconcileService frm;
+	protected ILinkDiscoveryService lds;
+	protected Map<Link, LinkInfo> links;
+	protected FloodlightContext cntx;
+	protected static boolean waiting = false;
+	protected int statsQueryXId;
+	protected static List<OFFlowStatisticsReply> statsReply;
+
+	// ITopologyListener
+	@Override
+	public void topologyChanged() {
+		for (LDUpdate ldu : topology.getLastLinkUpdates()) {
+			if (ldu.getOperation().equals(
+					ILinkDiscovery.UpdateOperation.PORT_DOWN)) {
+				
+				// Get the switch ID for the OFMatchWithSwDpid object
+				long affectedSwitch = floodlightProvider.getSwitches()
+						.get(ldu.getSrc()).getId();
+
+				// Create an OFMatchReconcile object
+				OFMatchReconcile ofmr = new OFMatchReconcile();
+
+				// Generate an OFMatch objects for the OFMatchWithSwDpid object
+				OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
+
+				// Generate the OFMatchWithSwDpid
+				OFMatchWithSwDpid ofmatchsw = new OFMatchWithSwDpid(match,
+						affectedSwitch);
+
+				// Set the action to update the path to remove flows routing
+				// towards the downed port
+				ofmr.rcAction = OFMatchReconcile.ReconcileAction.UPDATE_PATH;
+
+				// Set the match, with the switch dpid
+				ofmr.ofmWithSwDpid = ofmatchsw;
+
+				// Assign the downed port to the OFMatchReconcile's outPort data member (I added this to
+				// the OFMatchReconcile class)
+				ofmr.outPort = ldu.getSrcPort();
+
+				// Tell the reconcile manager to reconcile matching flows
+				frm.reconcileFlow(ofmr);
+			}
+		}
+	}
+	
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		return null;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+		return null;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IFloodlightProviderService.class);
+		l.add(ITopologyService.class);
+		l.add(IFlowReconcileService.class);
+		l.add(ILinkDiscoveryService.class);
+		return l;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		floodlightProvider = context
+				.getServiceImpl(IFloodlightProviderService.class);
+		topology = context.getServiceImpl(ITopologyService.class);
+		frm = context.getServiceImpl(IFlowReconcileService.class);
+		lds = context.getServiceImpl(ILinkDiscoveryService.class);
+		cntx = new FloodlightContext();
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context) {
+		topology.addListener((ITopologyListener) this);
+		frm.addFlowReconcileListener((IFlowReconcileListener) this);
+	}
+
+	@Override
+	public String getName() {
+		return "portdownreconciliation";
+	}
+
+	@Override
+	public boolean isCallbackOrderingPrereq(OFType type, String name) {
+		return false;
+	}
+
+	@Override
+	public boolean isCallbackOrderingPostreq(OFType type, String name) {
+		return true;
+	}
+
+	/**
+	 * Base case for the reconciliation of flows. This is triggered at the
+	 * switch which is immediately affected by the PORT_DOWN event
+	 * 
+	 * @return the Command whether to STOP or Continue
+	 */
+	@Override
+	public net.floodlightcontroller.core.IListener.Command reconcileFlows(
+			ArrayList<OFMatchReconcile> ofmRcList) {
+		if (lds != null) {
+			links = new HashMap<Link, LinkInfo>();
+			// Get all the switch links from the topology
+			if (lds.getLinks() != null)
+				links.putAll(lds.getLinks());
+
+			for (OFMatchReconcile ofmr : ofmRcList) {
+				// We only care about OFMatchReconcile objects that wish to
+				// update the path to a switch
+				if (ofmr.rcAction
+						.equals(OFMatchReconcile.ReconcileAction.UPDATE_PATH)) {
+					// Get the switch object from the OFMatchReconcile
+					IOFSwitch sw = floodlightProvider.getSwitches().get(
+							ofmr.ofmWithSwDpid.getSwitchDataPathId());
+
+					// Map data structure that holds the invalid matches and the ingress ports of those matches
+					Map<Short, List<OFMatch>> invalidBaseIngressAndMatches = new HashMap<Short, List<OFMatch>>();
+
+					// Get the invalid flows
+					List<OFFlowStatisticsReply> flows = getFlows(sw,
+							ofmr.outPort);
+
+					// Analyze all the flows with outPorts equaling the downed
+					// port and extract OFMatch's to trace back to neighbors
+					for (OFFlowStatisticsReply flow : flows) {
+						// Create a reference to the match for ease
+						OFMatch match = flow.getMatch();
+
+						// Here we utilize an index of input ports which point
+						// to multiple invalid matches
+						if (invalidBaseIngressAndMatches.containsKey(match
+								.getInputPort()))
+							// If the input port is already in the index, add
+							// the match to it's list
+							invalidBaseIngressAndMatches.get(
+									match.getInputPort()).add(match);
+						else {
+							// Otherwise create a new list and add it to the
+							// index
+							List<OFMatch> matches = new ArrayList<OFMatch>();
+							matches.add(match);
+							invalidBaseIngressAndMatches.put(
+									match.getInputPort(), matches);
+						}
+					}
+
+					// Remove invalid flows from the base switch, if they exist
+					if (!flows.isEmpty()) {
+						log.debug("Removing flows on switch : " + sw.getId()
+								+ " with outport: " + ofmr.outPort);
+						clearFlowMods(sw, ofmr.outPort);
+					}
+
+					// Create a list of neighboring switches we need to remove
+					// invalid flows from
+					Map<IOFSwitch, Map<Short, List<OFMatch>>> neighborSwitches = new HashMap<IOFSwitch, Map<Short, List<OFMatch>>>();
+
+					// Loop through all the links
+					for (Link link : links.keySet()) {
+						// Filter out links we care about
+						if (link.getDst() == sw.getId()) {
+							// Loop through the links to neighboring switches
+							// which have invalid flows
+							for (Entry<Short, List<OFMatch>> invalidBaseIngressAndMatch : invalidBaseIngressAndMatches
+									.entrySet()) {
+								// Find links on the network which link to the
+								// ingress ports that have invalidly routed
+								// flows
+								if (link.getDstPort() == invalidBaseIngressAndMatch
+										.getKey()) {
+									Map<Short, List<OFMatch>> invalidNeighborOutportAndMatch = new HashMap<Short, List<OFMatch>>();
+									// Insert the neighbor's outPort to the base
+									// switch and the invalid match
+									invalidNeighborOutportAndMatch.put(link
+											.getSrcPort(),
+											invalidBaseIngressAndMatch
+													.getValue());
+									// Link a neighbor switch's invalid match
+									// and outport to their Switch object
+									neighborSwitches.put(floodlightProvider
+											.getSwitches().get(link.getSrc()),
+											invalidNeighborOutportAndMatch);
+								}
+							}
+						}
+					}
+					log.debug("We have " + neighborSwitches.size()
+							+ " neighboring switches to deal with!");
+					// Loop through all the switches we found to have potential
+					// issues
+					for (IOFSwitch neighborSwitch : neighborSwitches.keySet()) {
+						log.debug("NeighborSwitch ID : "
+								+ neighborSwitch.getId());
+						if (neighborSwitches.get(neighborSwitch) != null)
+							deleteInvalidFlows(neighborSwitch,
+									neighborSwitches.get(neighborSwitch));
+					}
+				}
+				return Command.CONTINUE;
+			}
+		} else {
+			log.error("Link Discovery Service Is Null");
+		}
+		return Command.CONTINUE;
+	}
+	/**
+	 * 
+	 * @param sw
+	 *            the switch object that we wish to get flows from
+	 * @param outPort
+	 *            the output action port we wish to find flows with
+	 * @return a list of OFFlowStatisticsReply objects or essentially flows
+	 */
+	public List<OFFlowStatisticsReply> getFlows(IOFSwitch sw, Short outPort) {
+
+		statsReply = new ArrayList<OFFlowStatisticsReply>();
+		List<OFStatistics> values = null;
+		Future<List<OFStatistics>> future;
+
+		// Statistics request object for getting flows
+        OFStatisticsRequest req = new OFStatisticsRequest();
+        req.setStatisticType(OFStatisticsType.FLOW);
+        int requestLength = req.getLengthU();
+		OFFlowStatisticsRequest specificReq = new OFFlowStatisticsRequest();
+        specificReq.setMatch(new OFMatch().setWildcards(0xffffffff));
+        specificReq.setOutPort(outPort);
+        specificReq.setTableId((byte) 0xff);
+        req.setStatistics(Collections.singletonList((OFStatistics)specificReq));
+        requestLength += specificReq.getLength();
+        req.setLengthU(requestLength);
+        
+        try {
+        	//System.out.println(sw.getStatistics(req));
+        	future = sw.getStatistics(req);
+            values = future.get(10, TimeUnit.SECONDS);
+            if(values != null){
+            	for(OFStatistics stat : values){
+            		statsReply.add((OFFlowStatisticsReply)stat);
+            	}
+            }
+        } catch (Exception e) {
+            log.error("Failure retrieving statistics from switch " + sw, e);
+        }
+        
+        return statsReply;
+	}
+	
+	/**
+	 * 
+	 * @param sw The switch we wish to remove flows from
+	 * @param outPort The specific Output Action OutPort of specific flows we wish to delete
+	 */
+	public void clearFlowMods(IOFSwitch sw, Short outPort) {
+        // Delete all pre-existing flows with the same output action port or outPort
+    	OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
+        OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory()
+            .getMessage(OFType.FLOW_MOD))
+                .setMatch(match)
+            .setCommand(OFFlowMod.OFPFC_DELETE)
+            .setOutPort(outPort)
+            .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));
+        try {
+            List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+            msglist.add(fm);
+            sw.write(msglist, cntx);
+        } catch (Exception e) {
+            log.error("Failed to clear flows on switch {} - {}", this, e);
+        }
+    }
+    
+	/**
+	 * 
+	 * @param sw The switch we wish to remove flows from
+	 * @param match The specific OFMatch object of specific flows we wish to delete
+	 * @param outPort The specific Output Action OutPort of specific flows we wish to delete
+	 */
+    public void clearFlowMods(IOFSwitch sw, OFMatch match, Short outPort) { 
+        // Delete pre-existing flows with the same match, and output action port or outPort
+    	match.setWildcards(OFMatch.OFPFW_ALL);
+        OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory()
+            .getMessage(OFType.FLOW_MOD))
+                .setMatch(match)
+            .setCommand(OFFlowMod.OFPFC_DELETE)
+            .setOutPort(outPort)
+            .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));
+        try {
+            List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+            msglist.add(fm);
+            sw.write(msglist, cntx);
+        } catch (Exception e) {
+            log.error("Failed to clear flows on switch {} - {}", this, e);
+        }
+    }
+
+	/**
+	 * Deletes flows with similar matches and output action ports on the
+	 * specified switch
+	 * 
+	 * @param sw
+	 *            the switch to query flows on
+	 * @param match
+	 *            the problematic OFMatch from the base switch which we wish to
+	 *            find and remove
+	 * @param outPort
+	 *            the output action port wanted from the flows, which follows
+	 *            the route to the base switch
+	 */
+	public void deleteInvalidFlows(IOFSwitch sw,
+			Map<Short, List<OFMatch>> invalidOutportAndMatch) {
+		log.debug("Deleting invalid flows on switch : " + sw.getId());
+
+		// A map that holds the input ports and invalid matches on a switch
+		Map<Short, List<OFMatch>> invalidNeighborIngressAndMatches = new HashMap<Short, List<OFMatch>>();
+
+		for (Short outPort : invalidOutportAndMatch.keySet()) {
+			// Get the flows on the switch
+			List<OFFlowStatisticsReply> flows = getFlows(sw, outPort);
+
+			// Analyze all the flows with outPorts pointing to problematic route
+			for (OFFlowStatisticsReply flow : flows) {
+				// Loop through all the problematic matches
+				for (OFMatch match : invalidOutportAndMatch.get(outPort)) {
+					// Compare the problematic matches with the match of the flow on the switch
+					if (HexString.toHexString(
+							flow.getMatch().getDataLayerDestination()).equals(
+							HexString.toHexString(match
+									.getDataLayerDestination()))
+							&& HexString.toHexString(
+									flow.getMatch().getDataLayerSource())
+									.equals(HexString.toHexString(match
+											.getDataLayerSource()))
+							&& flow.getMatch().getDataLayerType() == match
+									.getDataLayerType()
+							&& flow.getMatch().getDataLayerVirtualLan() == match
+									.getDataLayerVirtualLan()
+							&& flow.getMatch().getNetworkDestination() == match
+									.getNetworkDestination()
+							&& flow.getMatch().getNetworkDestinationMaskLen() == match
+									.getNetworkDestinationMaskLen()
+							&& flow.getMatch().getNetworkProtocol() == match
+									.getNetworkProtocol()
+							&& flow.getMatch().getNetworkSource() == match
+									.getNetworkSource()
+							&& flow.getMatch().getNetworkSourceMaskLen() == match
+									.getNetworkSourceMaskLen()
+							&& flow.getMatch().getNetworkTypeOfService() == match
+									.getNetworkTypeOfService()) {
+
+						// Here we utilize an index of input ports which point
+						// to multiple invalid matches
+						if (invalidNeighborIngressAndMatches.containsKey(match
+								.getInputPort()))
+							// If the input port is already in the index, add
+							// the match to it's list
+							invalidNeighborIngressAndMatches.get(
+									match.getInputPort()).add(match);
+						else {
+							// Otherwise create a new list and add it to the
+							// index
+							List<OFMatch> matches = new ArrayList<OFMatch>();
+							matches.add(match);
+							invalidNeighborIngressAndMatches.put(
+									match.getInputPort(), matches);
+						}
+						// Remove flows from the switch with the invalid match and outPort
+						clearFlowMods(sw, flow.getMatch(), outPort);
+					}
+				}
+			}
+
+			// Create a list of neighboring switches we need to check for
+			// invalid flows
+			Map<IOFSwitch, Map<Short, List<OFMatch>>> neighborSwitches = new HashMap<IOFSwitch, Map<Short, List<OFMatch>>>();
+
+			// Loop through all the links
+			for (Link link : links.keySet()) {
+				// Filter out links we care about
+				if (link.getDst() == sw.getId()) {
+					// Loop through the ingressPorts that are involved in
+					// invalid flows on neighboring switches
+					for (Entry<Short, List<OFMatch>> ingressPort : invalidNeighborIngressAndMatches
+							.entrySet()) {
+						// Filter out invalid links by matching the link
+						// destination port to our invalid flows ingress port
+						if (link.getDstPort() == ingressPort.getKey()) {
+							// Generate a match and outPort map since I don't
+							// want to create an object
+							Map<Short, List<OFMatch>> invalidNeighborOutportAndMatch = new HashMap<Short, List<OFMatch>>();
+							invalidNeighborOutportAndMatch.put(
+									link.getSrcPort(), ingressPort.getValue());
+							// Link a neighbor switch's invalid match and
+							// outport to their Switch object
+							neighborSwitches.put(floodlightProvider
+									.getSwitches().get(link.getSrc()),
+									invalidNeighborOutportAndMatch);
+						}
+					}
+				}
+			}
+			log.debug("We have " + neighborSwitches.size()
+					+ " neighbors to deal with!");
+
+			// Loop through all the neighbor switches we found to have
+			// invalid matches
+			for (IOFSwitch neighborSwitch : neighborSwitches.keySet()) {
+				log.debug("NeighborSwitch ID : "
+						+ neighborSwitch.getId());
+				// Recursively seek out and delete invalid flows on the
+				// neighbor switch
+				deleteInvalidFlows(neighborSwitch,
+						neighborSwitches.get(neighborSwitch));
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/net/floodlightcontroller/flowcache/PortDownReconciliationTest.java b/src/test/java/net/floodlightcontroller/flowcache/PortDownReconciliationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..29912bfeb37761e6049918d5ef3f93a8cd27c7d7
--- /dev/null
+++ b/src/test/java/net/floodlightcontroller/flowcache/PortDownReconciliationTest.java
@@ -0,0 +1,460 @@
+/**
+ *    Copyright 2012, Jason Parraga, Marist College 
+ * 
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+package net.floodlightcontroller.flowcache;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMatchWithSwDpid;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFStatisticsRequest;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.protocol.statistics.OFFlowStatisticsReply;
+import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.openflow.protocol.statistics.OFStatisticsType;
+import org.openflow.util.U16;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.test.MockFloodlightProvider;
+import net.floodlightcontroller.core.test.MockThreadPoolService;
+import net.floodlightcontroller.devicemanager.IEntityClassifierService;
+import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier;
+import net.floodlightcontroller.flowcache.FlowReconcileManager;
+import net.floodlightcontroller.flowcache.IFlowReconcileService;
+import net.floodlightcontroller.flowcache.OFMatchReconcile;
+import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.floodlightcontroller.linkdiscovery.LinkInfo;
+import net.floodlightcontroller.routing.Link;
+import net.floodlightcontroller.test.FloodlightTestCase;
+import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.floodlightcontroller.topology.ITopologyService;
+
+/**
+ * Unit test for PortDownReconciliation. To test the class I have generated
+ * there very simple network topologies. an OFMatchReconcile object with
+ * information about the PORT_DOWN event is passed to the class, where it begins
+ * breaking down the information,analyzing the switches for flows and deleting
+ * those that are invalid. This Test specifically verifies that each switch is
+ * queried for flows once and is sent the appropriate OFFlowMod delete
+ * message.
+ * 
+ * @author Jason Parraga
+ */
+
+public class PortDownReconciliationTest extends FloodlightTestCase {
+
+	protected MockFloodlightProvider mockFloodlightProvider;
+	protected FloodlightModuleContext fmc;
+	protected ILinkDiscoveryService lds;
+	protected FlowReconcileManager flowReconcileMgr;
+	protected MockThreadPoolService tps;
+	protected DefaultEntityClassifier entityClassifier;
+	protected PortDownReconciliation pdr;
+	protected ITopologyService topology;
+	protected IOFSwitch sw1, sw2, sw3, sw4;
+	protected Map<Long, IOFSwitch> switches;
+	protected Capture<List<OFMessage>> wc1, wc2, wc3, wc4;
+	protected Capture<FloodlightContext> bc1, bc2, bc3, bc4;
+	protected OFMessage fmd, fmd2;
+	protected ArrayList<OFMatchReconcile> lofmr;
+	protected OFMatchReconcile ofmr;
+	protected static Logger log;
+	protected FloodlightContext cntx;
+	protected List<OFStatistics> statsReply;
+
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+
+		log = LoggerFactory.getLogger(PortDownReconciliation.class);
+		fmc = new FloodlightModuleContext();
+		mockFloodlightProvider = getMockFloodlightProvider();
+		pdr = new PortDownReconciliation();
+		lds = createMock(ILinkDiscoveryService.class);
+		entityClassifier = new DefaultEntityClassifier();
+		tps = new MockThreadPoolService();
+		flowReconcileMgr = new FlowReconcileManager();
+		topology = createMock(ITopologyService.class);
+		cntx = new FloodlightContext();
+		statsReply = new ArrayList<OFStatistics>();
+
+		fmc.addService(IThreadPoolService.class, tps);
+		fmc.addService(IFloodlightProviderService.class,
+				getMockFloodlightProvider());
+		fmc.addService(IFlowReconcileService.class, flowReconcileMgr);
+		fmc.addService(ITopologyService.class, topology);
+		fmc.addService(IEntityClassifierService.class, entityClassifier);
+		fmc.addService(ILinkDiscoveryService.class, lds);
+
+		tps.init(fmc);
+		flowReconcileMgr.init(fmc);
+		entityClassifier.init(fmc);
+		getMockFloodlightProvider().init(fmc);
+		pdr.init(fmc);
+
+		tps.startUp(fmc);
+		flowReconcileMgr.startUp(fmc);
+		entityClassifier.startUp(fmc);
+		getMockFloodlightProvider().startUp(fmc);
+		pdr.startUp(fmc);
+
+		// The STATS_REQUEST object used when querying the switches for flows
+		OFStatisticsRequest req = new OFStatisticsRequest();
+		req.setStatisticType(OFStatisticsType.FLOW);
+		int requestLength = req.getLengthU();
+		OFFlowStatisticsRequest specificReq = new OFFlowStatisticsRequest();
+		specificReq.setMatch(new OFMatch().setWildcards(0xffffffff));
+		specificReq.setOutPort((short) 3);
+		specificReq.setTableId((byte) 0xff);
+		req.setStatistics(Collections.singletonList((OFStatistics) specificReq));
+		requestLength += specificReq.getLength();
+		req.setLengthU(requestLength);
+
+		// Actions for the STATS_REPLY object
+		OFFlowMod flow = new OFFlowMod();
+		OFActionOutput action = new OFActionOutput((short) 3, (short) 0xffff);
+		List<OFAction> actions = new ArrayList<OFAction>();
+		actions.add(action);
+
+		// Match for the STATS_REPLY object
+		OFMatch m = new OFMatch();
+		// Set the incoming port to 1 so that it will find the connected
+		m.setInputPort((short) 1);
+
+		// STATS_REPLY object
+		OFFlowStatisticsReply reply = new OFFlowStatisticsReply();
+		reply.setActions(actions);
+		reply.setMatch(m);
+		// Add the reply to the list of OFStatistics
+		statsReply.add(reply);
+
+		// Create the STATS_REPLY asynchronous reply object
+		Callable<List<OFStatistics>> replyFuture = new ReplyFuture();
+		// Assign the callable object to a Futuretask so that it will produce future results
+		FutureTask<List<OFStatistics>> futureStats = new FutureTask<List<OFStatistics>>(
+				replyFuture);
+
+		// Assign the results of calling the object (the asynchronous reply)
+		Future<List<OFStatistics>> results = getResults(futureStats);
+
+		// SW1 -- Mock switch for base and multiple switch test case
+		sw1 = EasyMock.createNiceMock(IOFSwitch.class);
+		// Expect that the switch's ID is 1
+		expect(sw1.getId()).andReturn(1L).anyTimes();
+		expect(sw1.getStatistics(req)).andReturn(results).once();
+		// Captures to hold resulting flowmod delete messages
+		wc1 = new Capture<List<OFMessage>>(CaptureType.ALL);
+		bc1 = new Capture<FloodlightContext>(CaptureType.ALL);
+		// Capture the parameters passed when sw1.write is invoked
+		sw1.write(capture(wc1), capture(bc1));
+		expectLastCall().once();
+		replay(sw1);
+
+		// SW2 -- Mock switch for extended test cases
+		sw2 = EasyMock.createNiceMock(IOFSwitch.class);
+		// Expect that the switch's ID is 2
+		expect(sw2.getId()).andReturn(2L).anyTimes();
+		expect(sw2.getStatistics(req)).andReturn(results).once();
+		wc2 = new Capture<List<OFMessage>>(CaptureType.ALL);
+		bc2 = new Capture<FloodlightContext>(CaptureType.ALL);
+		// Capture the parameters passwed when sw1.write is invoked
+		sw2.write(capture(wc2), capture(bc2));
+		expectLastCall().anyTimes();
+		replay(sw2);
+
+		// SW3 -- Mock switch for extended test cases
+		sw3 = EasyMock.createNiceMock(IOFSwitch.class);
+		// Expect that the switch's ID is 3
+		expect(sw3.getId()).andReturn(3L).anyTimes();
+		expect(sw3.getStatistics(req)).andReturn(results).once();
+		wc3 = new Capture<List<OFMessage>>(CaptureType.ALL);
+		bc3 = new Capture<FloodlightContext>(CaptureType.ALL);
+		// Capture the parameters passwed when sw1.write is invoked
+		sw3.write(capture(wc3), capture(bc3));
+		expectLastCall().anyTimes();
+		replay(sw3);
+
+		// SW4 -- Mock switch for extended test cases
+		sw4 = EasyMock.createNiceMock(IOFSwitch.class);
+		// Expect that the switch's ID is 4
+		expect(sw4.getId()).andReturn(4L).anyTimes();
+		expect(sw4.getStatistics(req)).andReturn(results).once();
+		wc4 = new Capture<List<OFMessage>>(CaptureType.ALL);
+		bc4 = new Capture<FloodlightContext>(CaptureType.ALL);
+		// Capture the parameters passed when sw1.write is invoked
+		sw4.write(capture(wc4), capture(bc4));
+		expectLastCall().anyTimes();
+		replay(sw4);
+
+		// Here we create the OFMatch Reconcile list we wish to pass
+		lofmr = new ArrayList<OFMatchReconcile>();
+
+		// Create the only OFMatch Reconcile object that will be in the list
+		ofmr = new OFMatchReconcile();
+		long affectedSwitch = sw1.getId();
+		OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
+		OFMatchWithSwDpid ofmatchsw = new OFMatchWithSwDpid(match,
+				affectedSwitch);
+		ofmr.rcAction = OFMatchReconcile.ReconcileAction.UPDATE_PATH;
+		ofmr.ofmWithSwDpid = ofmatchsw;
+
+		// We'll say port 3 went down
+		ofmr.outPort = 3;
+
+		// Add the OFMatch Reconcile object to the list
+		lofmr.add(ofmr);
+
+		// Expected Flow Mod Deletes Messages
+		// Flow Mod Delete for base switch
+		fmd = ((OFFlowMod) mockFloodlightProvider.getOFMessageFactory()
+				.getMessage(OFType.FLOW_MOD))
+				.setMatch(new OFMatch().setWildcards(OFMatch.OFPFW_ALL))
+				.setCommand(OFFlowMod.OFPFC_DELETE)
+				// Notice we specify an outPort
+				.setOutPort((short) 3)
+				.setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));
+
+		// Flow Mod Delete for the neighborswitches
+		fmd2 = ((OFFlowMod) mockFloodlightProvider.getOFMessageFactory()
+				.getMessage(OFType.FLOW_MOD))
+				// Notice we used the base switch's flow's match
+				.setMatch(flow.getMatch())
+				.setCommand(OFFlowMod.OFPFC_DELETE)
+				// Notice we specific an outPort
+				.setOutPort((short) 3)
+				.setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));
+
+	}
+
+	// This generates the asynchronous reply to sw.getStatistics()
+	public Future<List<OFStatistics>> getResults(
+			FutureTask<List<OFStatistics>> futureStats) {
+		Thread t = new Thread(futureStats);
+		t.start();
+		return futureStats;
+
+	}
+
+	// Class for the asynchronous reply
+	public class ReplyFuture implements Callable<List<OFStatistics>> {
+		@Override
+		public List<OFStatistics> call() throws Exception {
+			// return stats reply defined above
+			return statsReply;
+		}
+	}
+
+	/**
+	 * This tests the port down reconciliation in the event that the base switch
+	 * is the only switch involved in the PORT_DOWN event. It simply deletes
+	 * flows concerning the downed port.
+	 * 
+	 * @verify checks to see that a general clearFlowMods(Short outPort) is
+	 *         called
+	 * @throws Exception
+	 */
+	@Test
+	public void testSingleSwitchPortDownReconciliation() throws Exception {
+		log.debug("Starting single switch port down reconciliation test");
+		// Load the switch map
+		switches = new HashMap<Long, IOFSwitch>();
+		switches.put(1L, sw1);
+		mockFloodlightProvider.setSwitches(switches);
+
+		// Reconcile flows with specified OFMatchReconcile
+		pdr.reconcileFlows(lofmr);
+		// Validate results
+		verify(sw1);
+
+		assertTrue(wc1.hasCaptured());
+
+		List<List<OFMessage>> msglist = wc1.getValues();
+
+		// Make sure the messages we captures correct
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd, m);
+		}
+	}
+
+	/**
+	 * This tests the port down reconciliation in the event that the base switch
+	 * is connected to a chain of three switches. It discovers that is has 1
+	 * neighbor, which recursively finds out that it has 1 neighbor until the
+	 * final switch "sw4" is evaluated, which has no neighbors.
+	 * 
+	 * @verify checks to see that a general clearFlowMods(Short outPort) is
+	 *         called on the base switch while specific clearFlowMods(OFMatch
+	 *         match, Short outPort) are called on the neighboring switches
+	 * @throws Exception
+	 */
+	@Test
+	public void testLinearLinkPortDownReconciliation() throws Exception {
+		log.debug("Starting linear link port down reconciliation test");
+
+		// Load the switch map
+		switches = new HashMap<Long, IOFSwitch>();
+		switches.put(1L, sw1);
+		switches.put(2L, sw2);
+		switches.put(3L, sw3);
+		switches.put(4L, sw4);
+		mockFloodlightProvider.setSwitches(switches);
+
+		// Create the links between the switches
+		// (Switch 4) --> (Switch 3) --> (Switch 2) --> (Switch 1)
+		Map<Link, LinkInfo> links = new HashMap<Link, LinkInfo>();
+		Link link = new Link(2L, (short) 3, 1L, (short) 1);
+		Link link2 = new Link(3L, (short) 3, 2L, (short) 1);
+		Link link3 = new Link(4L, (short) 3, 3L, (short) 1);
+		LinkInfo linkinfo = null;
+		links.put(link, linkinfo);
+		links.put(link2, linkinfo);
+		links.put(link3, linkinfo);
+
+		// Make sure that the link discovery service provides the link we made
+		expect(lds.getLinks()).andReturn(links).anyTimes();
+		replay(lds);
+
+		// Reconcile flows with specified OFMatchReconcile
+		pdr.reconcileFlows(lofmr);
+		// Validate results
+		verify(sw1, sw2, sw3, sw4);
+
+		// Make sure each capture is not null
+		assertTrue(wc2.hasCaptured());
+		assertTrue(wc3.hasCaptured());
+		assertTrue(wc4.hasCaptured());
+
+		// Make sure each capture has captured the proper Flow Mod Delete
+		// message
+		List<List<OFMessage>> msglist = wc2.getValues();
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd2, m);
+		}
+
+		msglist = wc3.getValues();
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd2, m);
+		}
+
+		msglist = wc4.getValues();
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd2, m);
+		}
+	}
+
+	/**
+	 * This tests the port down reconciliation in the event that the base switch
+	 * has three separate neighboring switches with invalid flows. It discovers
+	 * that is has 3 neighbors and each of them delete flows with the specific
+	 * OFMatch and outPort.
+	 * 
+	 * @verify checks to see that a general clearFlowMods(Short outPort) is
+	 *         called on the base switch while specific clearFlowMods(OFMatch
+	 *         match, Short outPort) are called on the neighboring switches
+	 * @throws Exception
+	 */
+	@Test
+	public void testMultipleLinkPortDownReconciliation() throws Exception {
+		log.debug("Starting multiple link port down reconciliation test");
+
+		// Load the switch map
+		switches = new HashMap<Long, IOFSwitch>();
+		switches.put(1L, sw1);
+		switches.put(2L, sw2);
+		switches.put(3L, sw3);
+		switches.put(4L, sw4);
+		mockFloodlightProvider.setSwitches(switches);
+
+		// Create the links between the switches
+		// (Switch 4 output port 3) --> (Switch 1 input port 1)
+		// (Switch 3 output port 3) --> (Switch 1 input port 1)
+		// (Switch 2 output port 3) --> (Switch 1 input port 1)
+		Map<Link, LinkInfo> links = new HashMap<Link, LinkInfo>();
+		Link link = new Link(2L, (short) 3, 1L, (short) 1);
+		Link link2 = new Link(3L, (short) 3, 1L, (short) 1);
+		Link link3 = new Link(4L, (short) 3, 1L, (short) 1);
+		LinkInfo linkinfo = null;
+		links.put(link, linkinfo);
+		links.put(link2, linkinfo);
+		links.put(link3, linkinfo);
+
+		// Make sure that the link discovery service provides the link we made
+		expect(lds.getLinks()).andReturn(links).anyTimes();
+		replay(lds);
+
+		// Reconcile flows with specified OFMatchReconcile
+		pdr.reconcileFlows(lofmr);
+		// Validate results
+		verify(sw1, sw2, sw3, sw4);
+
+		// Make sure each capture is not null
+		assertTrue(wc2.hasCaptured());
+		assertTrue(wc3.hasCaptured());
+		assertTrue(wc4.hasCaptured());
+
+		// Make sure each capture has captured the proper Flow Mod Delete
+		// message
+		List<List<OFMessage>> msglist = wc2.getValues();
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd2, m);
+		}
+
+		msglist = wc3.getValues();
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd2, m);
+		}
+
+		msglist = wc4.getValues();
+		for (List<OFMessage> m : msglist) {
+			if (m instanceof OFFlowMod)
+				assertEquals(fmd2, m);
+		}
+	}
+}
\ No newline at end of file