diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java index 48d5e61321518af386075efed9f0356d711bfd0a..79cb2699bab7b8da1d6fc6700a7fbbeb1445442c 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java @@ -42,13 +42,13 @@ public interface IDeviceService extends IFloodlightService { * The source device for the current packet-in, if applicable. */ public static final String CONTEXT_SRC_DEVICE = - "com.bigswitch.floodlight.devicemanager.srcDevice"; + "net.floodlightcontroller.devicemanager.srcDevice"; /** * The destination device for the current packet-in, if applicable. */ public static final String CONTEXT_DST_DEVICE = - "com.bigswitch.floodlight.devicemanager.dstDevice"; + "net.floodlightcontroller.devicemanager.dstDevice"; /** * A FloodlightContextStore object that can be used to interact with the diff --git a/src/main/java/net/floodlightcontroller/flowcache/FCQueryObj.java b/src/main/java/net/floodlightcontroller/flowcache/FCQueryObj.java new file mode 100644 index 0000000000000000000000000000000000000000..058820b4065b2ed0ffcf4230d0cdad6f6db235dd --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/FCQueryObj.java @@ -0,0 +1,52 @@ +package net.floodlightcontroller.flowcache; + +import java.util.Arrays; + +import net.floodlightcontroller.devicemanager.IDevice; +import net.floodlightcontroller.flowcache.IFlowCacheService.FCQueryEvType; +import net.floodlightcontroller.flowcache.IFlowCacheService.FCQueryType; + + +/** + * The Class FCQueryObj. + */ +public class FCQueryObj { + + /** The caller of the flow cache query. */ + public IFlowQueryHandler fcQueryHandler; + /** The query type. */ + public FCQueryType queryType; + /** The application instance name. */ + public String applInstName; + /** The vlan Id. */ + public Short[] vlans; + /** The destination device. */ + public IDevice dstDevice; + /** The source device. */ + public IDevice srcDevice; + /** The caller name */ + public String callerName; + /** Event type that triggered this flow query submission */ + public FCQueryEvType evType; + /** The caller opaque data. Returned unchanged in the query response + * via the callback. The type of this object could be different for + * different callers */ + public Object callerOpaqueObj; + + /** + * Instantiates a new flow cache query object + */ + public FCQueryObj() { + queryType = FCQueryType.UNKNOWN; + } + + @Override + public String toString() { + return "FCQueryObj [fcQueryCaller=" + fcQueryHandler + + ", queryType=" + queryType + ", applInstName=" + + applInstName + ", vlans=" + Arrays.toString(vlans) + + ", dstDevice=" + dstDevice + ", srcDevice=" + + srcDevice + ", callerName=" + callerName + ", evType=" + + evType + ", callerOpaqueObj=" + callerOpaqueObj + "]"; + } +} diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowCacheQueryResp.java b/src/main/java/net/floodlightcontroller/flowcache/FlowCacheQueryResp.java new file mode 100644 index 0000000000000000000000000000000000000000..cb15ee6bb2d131d1a9cdca29cacfc669b8c7288e --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/FlowCacheQueryResp.java @@ -0,0 +1,51 @@ +package net.floodlightcontroller.flowcache; + +import java.util.ArrayList; + +/** + * Object to return flows in response to a query message to BigFlowCache. + * This object is passed in the flowQueryRespHandler() callback. + */ +public class FlowCacheQueryResp { + + /** query object provided by the caller, returned unchanged. */ + public FCQueryObj queryObj; + /** + * Set to true if more flows could be returned for this query in + * additional callbacks. Set of false in the last callback for the + * query. + */ + public boolean moreFlag; + /** + * The flow list. If there are large number of flows to be returned + * then they may be returned in multiple callbacks. + */ + public ArrayList<QRFlowCacheObj> qrFlowCacheObjList; + + /** + * Instantiates a new big flow cache query response. + * + * @param query the flow cache query object as given by the caller of + * flow cache submit query API. + */ + public FlowCacheQueryResp(FCQueryObj query) { + qrFlowCacheObjList = new ArrayList<QRFlowCacheObj>(); + queryObj = query; + moreFlag = false; + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + String s = queryObj.toString(); + if (moreFlag) { + s += "; moreFlasg=True"; + } else { + s += "; moreFlag=False"; + } + s += "; FlowCount=" + Integer.toString(qrFlowCacheObjList.size()); + return s; + } +} diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java index fc7fb110ea7ecbc0e33ac86411a4c9c658e14573..f977dbc3ec75667974c1ac58d5d448762b430890 100644 --- a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java +++ b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java @@ -10,6 +10,8 @@ import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.util.ListenerDispatcher; +import net.floodlightcontroller.devicemanager.IDevice; +import net.floodlightcontroller.flowcache.IFlowCacheService.FCQueryEvType; import net.floodlightcontroller.flowcache.IFlowReconcileListener; import net.floodlightcontroller.flowcache.OFMatchReconcile; @@ -86,6 +88,31 @@ public class FlowReconcileManager } } + @Override + public void updateFlowForDestinationDevice(IDevice device, FCQueryEvType fcEvType){ + // NO-OP + } + + @Override + public void updateFlowForSourceDevice(IDevice device, FCQueryEvType fcEvType){ + // NO-OP + } + + @Override + public void flowQueryGenericHandler(FlowCacheQueryResp flowResp) { + if (flowResp.queryObj.evType != FCQueryEvType.GET) { + OFMatchReconcile ofmRc = newOFMatchReconcile(); + /* Re-provision these flows */ + for (QRFlowCacheObj entry : flowResp.qrFlowCacheObjList) { + /* reconcile the flows in entry */ + entry.toOFMatchReconcile(ofmRc, flowResp.queryObj.applInstName, + OFMatchReconcile.ReconcileAction.UPDATE_PATH); + reconcileFlow(ofmRc); + } + } + return; + } + // IFloodlightModule @Override diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowCacheService.java b/src/main/java/net/floodlightcontroller/flowcache/IFlowCacheService.java new file mode 100644 index 0000000000000000000000000000000000000000..ad489041224162e59cb29104ac30ab20195ac4b2 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/IFlowCacheService.java @@ -0,0 +1,275 @@ +package net.floodlightcontroller.flowcache; + +import org.openflow.protocol.OFMatchWithSwDpid; + +import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.FloodlightContextStore; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.devicemanager.SwitchPort; +import net.floodlightcontroller.devicemanager.IDevice; +import net.floodlightcontroller.core.module.IFloodlightService; + +/** + * The Interface IFlowCache. + * <p> + * public interface APIs to Big Switch Flow-Cache Service. Flow-Cache maintains + * the network-level flows that are currently deployed in the underlying + * network. The flow cache can be queried using various filters by using the + * corresponding APIs. + * + * @author subrata + * + */ +public interface IFlowCacheService extends IFloodlightService { + + public static final String FLOWCACHE_APP_NAME = + "net.floodlightcontroller.flowcache.appName"; + public static final String FLOWCACHE_APP_INSTANCE_NAME = + "net.floodlightcontroller.flowcache.appInstanceName"; + + /** + * The Enum FCQueryType. + */ + public enum FCQueryType { + APPLINSTNAME, // The APPLINSTNAME. + APPLINSTNAME_VLAN, // The APPLINSTNAM e_ vlan. + ALLAPP_DESTDEVICE, // The destdevice for all application. + ALLAPP_SRCDEVICE, // The source device for all application. + ALLAPP_SRCDEVICE_DESTDEVICE, // The APPLINSTNAM srcdevic destdevice. + UNKNOWN, // The UNKNOWN. + } + + /** + * The flow cache query event type indicating the event that triggered the + * query. The callerOpaqueObj can be keyed based on this event type + */ + public static enum FCQueryEvType { + /** The GET query. Flows need not be reconciled for this query type */ + GET, + /** A new App was added. */ + APP_ADDED, + /** An App was deleted. */ + APP_DELETED, + /** Interface rule of an app was modified */ + APP_INTERFACE_RULE_CHANGED, + /** Some App configuration was changed */ + APP_CONFIG_CHANGED, + /** An ACL was added */ + ACL_ADDED, + /** An ACL was deleted */ + ACL_DELETED, + /** An ACL rule was added */ + ACL_RULE_ADDED, + /** An ACL rule was deleted */ + ACL_RULE_DELETED, + /** ACL configuration was changed */ + ACL_CONFIG_CHANGED, + /** device had moved to a different port in the network */ + DEVICE_MOVED, + /** device's property had changed, such as tag assignment */ + DEVICE_PROPERTY_CHANGED, + /** Link down */ + LINK_DOWN, + /** Periodic scan of switch flow table */ + PERIODIC_SCAN, + } + + /** + * A FloodlightContextStore object that can be used to interact with the + * FloodlightContext information about flowCache. + */ + public static final FloodlightContextStore<String> fcStore = + new FloodlightContextStore<String>(); + + /** + * Submit a flow cache query with query parameters specified in FCQueryObj + * object. The query object can be created using one of the newFCQueryObj + * helper functions in IFlowCache interface. + * <p> + * The queried flows are returned via the flowQueryRespHandler() callback + * that the caller must implement. The caller can match the query with + * the response using unique callerOpaqueData which remains unchanged + * in the request and response callback. + * + * @see com.bigswitch.floodlight.flowcache#flowQueryRespHandler + * @param query the flow cache query object as input + * + */ + public void submitFlowCacheQuery(FCQueryObj query); + + /** + * Get a new flow cache query object populated with the supplied parameters. + * The query type field id populated automatically based on the parameters + * passed. + * + * @param fcQueryCaller the caller of this API + * @param applInstName the application instance name + * @param callerOpaqueData opaque data passed by the caller which is + * returned unchanged in the corresponding callback. + * @return a new initialized flow cache query object + */ + public FCQueryObj newFCQueryObj(IFlowQueryHandler fcQueryHandler, + String applInstName, + String callerName, + FCQueryEvType evType, + Object callerOpaqueObj); + + /** + * Get a new flow cache query object populated with the supplied parameters. + * The query type field id populated automatically based on the parameters + * passed. + * + * @param fcQueryCaller the caller of this API + * @param applInstName the application instance name + * @param vlan VLAN ID + * @param callerOpaqueData opaque data passed by the caller which is + * returned unchanged in the corresponding callback. + * @return a new initialized flow cache query object + */ + public FCQueryObj newFCQueryObj(IFlowQueryHandler fcQueryHandler, + String applInstName, + short vlan, + String callerName, + FCQueryEvType evType, + Object callerOpaqueObj); + + /** + * Get a new flow cache query object populated with the supplied parameters. + * The query type field id populated automatically based on the parameters + * passed. + * + * @param fcQueryCaller the caller of this API + * @param applInstName the application instance name + * @param srcDevice source device object + * @param dstDevice destination device object + * @param callerOpaqueData opaque data passed by the caller which is + * returned unchanged in the corresponding callback. + * @return a new initialized flow cache query object + */ + public FCQueryObj newFCQueryObj(IFlowQueryHandler fcQueryHandler, + IDevice srcDevice, + IDevice dstDevice, + String callerName, + FCQueryEvType evType, + Object callerOpaqueObj); + + /** + * Get a new flow cache query object populated with the supplied parameters. + * The query type field id populated automatically based on the parameters + * passed. + * + * @return a new uninitialized flow cache query object + */ + public FCQueryObj newFCQueryObj(); + + /** + * Deactivates all flows in the flow cache for which the source switch + * matches the given switchDpid. Note that the flows are NOT deleted + * from the cache. + * + * @param switchDpid Data-path identifier of the source switch + */ + public void deactivateFlowCacheBySwitch(long switchDpid); + + /** + * Deletes all flows in the flow cache for which the source switch + * matches the given switchDpid. + * + * @param switchDpid Data-path identifier of the source switch + */ + public void deleteFlowCacheBySwitch(long switchDpid); + + /** + * Add a flow to the flow-cache - called when a flow-mod is about to be + * written to a set of switches. If it returns false then it should not + * be written to the switches. If it returns true then the cookie returned + * should be used for the flow mod sent to the switches. + * + * @param appInstName Application instance name + * @param ofm openflow match object + * @param cookie openflow-mod cookie + * @param swPort SwitchPort object + * @param priority openflow match priority + * @param action action taken on the matched packets (PERMIT or DENY) + * @return true: flow should be written to the switch(es) + * false: flow should not be written to the switch(es). false is + * returned, for example, when the flow was recently + * written to the flow-cache and hence it is dampened to + * avoid frequent writes of the same flow to the switches + * This case can typically arise for the flows written at the + * internal ports as they are heavily wild-carded. + */ + public boolean addFlow(String appInstName, OFMatchWithSwDpid ofm, + Long cookie, long srcSwDpid, + short inPort, short priority, byte action); + + /** + * Add a flow to the flow-cache - called when a flow-mod is about to be + * written to a set of switches. If it returns false then it should not + * be written to the switches. If it returns true then the cookie returned + * should be used for the flow mod sent to the switches. + * + * @param cntx the cntx + * @param ofm the ofm + * @param cookie the cookie + * @param swPort the sw port + * @param priority the priority + * @param action the action + * @return true: flow should be written to the switch(es) + * false: flow should not be written to the switch(es). false is + * returned, for example, when the flow was recently + * written to the flow-cache and hence it is dampened to + * avoid frequent writes of the same flow to the switches + * This case can typically arise for the flows written at the + * internal ports as they are heavily wild-carded. + */ + public boolean addFlow(FloodlightContext cntx, OFMatchWithSwDpid ofm, + Long cookie, SwitchPort swPort, + short priority, byte action); + + /** + * Move the specified flow from its current application instance to a + * different application instance. This API can be used when a flow moves + * to a different application instance when the application instance + * configuration changes or when a device moves to a different part in + * the network that belongs to a different application instance. + * <p> + * Note that, if the flow was not found in the current application + * instance then the flow is not moved to the new application instance. + * + * @param ofMRc the object containing the flow match and new application + * instance name. + * @return true is the flow was found in the flow cache in the current + * application instance; false if the flow was not found in the flow-cache + * in the current application instance. + */ + public boolean moveFlowToDifferentApplInstName(OFMatchReconcile ofMRc); + + /** + * Move all the flows from their current application instance to a + * different application instance. This API can be used when all flows in + * an application instance move to a different application instance when + * the application instance configuration changes. + * + * @param curApplInstName current application instance name + * @param newApplInstName new application instance name + */ + public void moveFlowToDifferentApplInstName(String curApplInstName, + String newApplInstName); + + /** + * Delete all flow from the specified switch + * @param sw + */ + public void deleteAllFlowsAtASourceSwitch(IOFSwitch sw); + + /** + * Post a request to update flowcache from a switch. + * This is an asynchronous operation. + * It queries the switch for stats and updates the flowcache asynchronously + * with the response. + * @param swDpid + * @param delay_ms + */ + public void querySwitchFlowTable(long swDpid); +} diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowQueryHandler.java b/src/main/java/net/floodlightcontroller/flowcache/IFlowQueryHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..5d1b1a9dea7b2f6d4c97c11cb1ed120df5bbc047 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/IFlowQueryHandler.java @@ -0,0 +1,21 @@ +package net.floodlightcontroller.flowcache; + +public interface IFlowQueryHandler { + /** + * This callback function is called in response to a flow query request + * submitted to the flow cache service. The module handling this callback + * can be different from the one that submitted the query. In the flow + * query object used for submitting the flow query, the identity of the + * callback handler is passed. When flow cache service has all or some + * of the flows that needs to be returned then this callback is called + * for the appropriate module. The respone contains a boolean more flag + * that indicates if there are additional flows that may be returned + * via additional callback calls. + * + * @param resp the response object containing the original flow query + * object, partial or complete list of flows that we queried and some + * metadata such as the more flag described aboce. + * + */ + public void flowQueryRespHandler(FlowCacheQueryResp resp); +} diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowReconcileService.java b/src/main/java/net/floodlightcontroller/flowcache/IFlowReconcileService.java index 182b685b34fac67aeab762e400298663c7128f1c..387c7d57c36cf488b48d36549b4077f0572f347c 100644 --- a/src/main/java/net/floodlightcontroller/flowcache/IFlowReconcileService.java +++ b/src/main/java/net/floodlightcontroller/flowcache/IFlowReconcileService.java @@ -5,6 +5,8 @@ package net.floodlightcontroller.flowcache; import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.devicemanager.IDevice; +import net.floodlightcontroller.flowcache.IFlowCacheService.FCQueryEvType; public interface IFlowReconcileService extends IFloodlightService { /** @@ -32,5 +34,36 @@ public interface IFlowReconcileService extends IFloodlightService { * @param ofmRcIn the ofm rc in */ public void reconcileFlow(OFMatchReconcile ofmRcIn); + + /** + * Updates the flows to a device after the device moved to a new location + * <p> + * Queries the flow-cache to get all the flows destined to the given device. + * Reconciles each of these flows by potentially reprogramming them to its + * new attachment point + * + * @param device device that has moved + * @param fcEvType Event type that triggered the update + * + */ + public void updateFlowForDestinationDevice(IDevice device, FCQueryEvType fcEvType); + + /** + * Updates the flows from a device + * <p> + * Queries the flow-cache to get all the flows source from the given device. + * Reconciles each of these flows by potentially reprogramming them to its + * new attachment point + * + * @param device device where the flow originates + * @param fcEvType Event type that triggered the update + * + */ + public void updateFlowForSourceDevice(IDevice device, FCQueryEvType fcEvType); + /** + * Generic flow query handler to insert FlowMods into the reconcile pipeline. + * @param flowResp + */ + public void flowQueryGenericHandler(FlowCacheQueryResp flowResp); } diff --git a/src/main/java/net/floodlightcontroller/flowcache/PendingSwRespKey.java b/src/main/java/net/floodlightcontroller/flowcache/PendingSwRespKey.java new file mode 100644 index 0000000000000000000000000000000000000000..767ce94c0479382bf5db9e7ba5880cc8db889fd3 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/PendingSwRespKey.java @@ -0,0 +1,42 @@ +package net.floodlightcontroller.flowcache; + +public class PendingSwRespKey { + long swDpid; + int transId; + + public PendingSwRespKey(long swDpid, int transId) { + this.swDpid = swDpid; + this.transId = transId; + } + + @Override + public int hashCode() { + final int prime = 97; + Long dpid = swDpid; + Integer tid = transId; + return (tid.hashCode()*prime + dpid.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof PendingSwRespKey)) { + return false; + } + PendingSwRespKey other = (PendingSwRespKey) obj; + if ((swDpid != other.swDpid) || (transId != other.transId)) { + return false; + } + return true; + } + + @Override + public String toString() { + return Long.toHexString(swDpid)+","+Integer.toString(transId); + } +} diff --git a/src/main/java/net/floodlightcontroller/flowcache/PendingSwitchResp.java b/src/main/java/net/floodlightcontroller/flowcache/PendingSwitchResp.java new file mode 100644 index 0000000000000000000000000000000000000000..d6f264fccb22afaac8206eb6be2f9ccbc8cb3eff --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/PendingSwitchResp.java @@ -0,0 +1,24 @@ +package net.floodlightcontroller.flowcache; + +import net.floodlightcontroller.flowcache.IFlowCacheService.FCQueryEvType; + +/** + * The Class PendingSwitchResp. This object is used to track the pending + * responses to switch flow table queries. + */ +public class PendingSwitchResp { + protected FCQueryEvType evType; + + public PendingSwitchResp( + FCQueryEvType evType) { + this.evType = evType; + } + + public FCQueryEvType getEvType() { + return evType; + } + + public void setEvType(FCQueryEvType evType) { + this.evType = evType; + } +} diff --git a/src/main/java/net/floodlightcontroller/flowcache/QRFlowCacheObj.java b/src/main/java/net/floodlightcontroller/flowcache/QRFlowCacheObj.java new file mode 100644 index 0000000000000000000000000000000000000000..5121f8bb9704512861b0a853ed5fd86f7cead49b --- /dev/null +++ b/src/main/java/net/floodlightcontroller/flowcache/QRFlowCacheObj.java @@ -0,0 +1,67 @@ +package net.floodlightcontroller.flowcache; + + +import org.openflow.protocol.OFMatchWithSwDpid; + +/** + * Used in BigFlowCacheQueryResp as query result. + * Used to return one flow when queried by one of the big flow cache APIs. + * One of these QRFlowCacheObj is returned for each combination of + * priority and action. + * + * @author subrata + */ +public class QRFlowCacheObj { + + /** The open flow match object. */ + public OFMatchWithSwDpid ofmWithSwDpid; + /** The flow-mod priority. */ + public short priority; + /** flow-mod cookie */ + public long cookie; + /** The action - PERMIT or DENY. */ + public byte action; + /** The reserved byte to align with 8 bytes. */ + public byte reserved; + + /** + * Instantiates a new flow cache query object. + * + * @param priority the priority + * @param action the action + */ + public QRFlowCacheObj(short priority, byte action, long cookie) { + ofmWithSwDpid = new OFMatchWithSwDpid(); + this.action = action; + this.priority = priority; + this.cookie = cookie; + } + + /** + * Populate a given OFMatchReconcile object from the values of this + * class. + * + * @param ofmRc the given OFMatchReconcile object + * @param appInstName the application instance name + * @param rcAction the reconcile action + */ + public void toOFMatchReconcile(OFMatchReconcile ofmRc, + String appInstName, OFMatchReconcile.ReconcileAction rcAction) { + ofmRc.ofmWithSwDpid = ofmWithSwDpid; // not copying + ofmRc.appInstName = appInstName; + ofmRc.rcAction = rcAction; + ofmRc.priority = priority; + ofmRc.cookie = cookie; + ofmRc.action = action; + } + + @Override + public String toString() { + String str = "ofmWithSwDpid: " + this.ofmWithSwDpid.toString() + " "; + str += "priority: " + this.priority + " "; + str += "cookie: " + this.cookie + " "; + str += "action: " + this.action + " "; + str += "reserved: " + this.reserved + " "; + return str; + } +}