diff --git a/src/main/java/net/floodlightcontroller/core/util/AppCookie.java b/src/main/java/net/floodlightcontroller/core/util/AppCookie.java index 370256fb1596f98aee6f1946b4008f8f26e2f3b4..d35e6a9e56631e21f3c13f52db9b6f693199fe76 100644 --- a/src/main/java/net/floodlightcontroller/core/util/AppCookie.java +++ b/src/main/java/net/floodlightcontroller/core/util/AppCookie.java @@ -76,6 +76,13 @@ public class AppCookie { return U64.of(APP_ID_MASK << APP_ID_SHIFT); } + /** + * Returns a mask suitable for matching the User field within a cookie. + */ + static public U64 getUserFieldMask() { + return U64.of(USER_MASK); + } + /** * Encapsulate an application ID and a user block of stuff into a cookie * diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java index 0fb28b24c46b73002f63830800bd812c3922595f..f5bb37e8181446347294b7720bb423383e80deb2 100644 --- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java +++ b/src/main/java/net/floodlightcontroller/firewall/Firewall.java @@ -37,6 +37,7 @@ import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IPv4AddressWithMask; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.Masked; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U64; @@ -60,6 +61,7 @@ import net.floodlightcontroller.packet.TCP; import net.floodlightcontroller.packet.UDP; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.routing.IRoutingDecision; +import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.RoutingDecision; import net.floodlightcontroller.storage.IResultSet; import net.floodlightcontroller.storage.IStorageSourceService; @@ -85,11 +87,13 @@ IFloodlightModule { private static final U64 DENY_BCAST_COOKIE = AppCookie.makeCookie(APP_ID, 0xaaaaaaaa); private static final U64 ALLOW_BCAST_COOKIE = AppCookie.makeCookie(APP_ID, 0x55555555); private static final U64 RULE_MISS_COOKIE = AppCookie.makeCookie(APP_ID, -1); + private static final U64 DEFAULT_COOKIE = AppCookie.makeCookie(APP_ID, 0); // service modules needed protected IFloodlightProviderService floodlightProvider; protected IStorageSourceService storageSource; protected IRestApiService restApi; + protected IRoutingService routingService; protected static Logger logger; protected List<FirewallRule> rules; // protected by synchronized @@ -170,6 +174,7 @@ IFloodlightModule { l.add(IFloodlightProviderService.class); l.add(IStorageSourceService.class); l.add(IRestApiService.class); + l.add(IRoutingService.class); return l; } @@ -288,6 +293,7 @@ IFloodlightModule { floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); storageSource = context.getServiceImpl(IStorageSourceService.class); restApi = context.getServiceImpl(IRestApiService.class); + routingService = context.getServiceImpl(IRoutingService.class); rules = new ArrayList<FirewallRule>(); logger = LoggerFactory.getLogger(Firewall.class); @@ -335,8 +341,18 @@ IFloodlightModule { @Override public void enableFirewall(boolean enabled) { - logger.info("Setting firewall to {}", enabled); - this.enabled = enabled; + + if(this.enabled != enabled) { + logger.info("Setting firewall to {}", enabled); + this.enabled = enabled; + + List<Masked<U64>> changes = new ArrayList<Masked<U64>>(); + changes.add(Masked.of(DEFAULT_COOKIE, AppCookie.getAppFieldMask())); + + // Add announcement that all firewall decisions changed + routingService.handleRoutingDecisionChange(changes); + } + } @Override @@ -424,6 +440,22 @@ IFloodlightModule { entry.put(COLUMN_PRIORITY, Integer.toString(rule.priority)); entry.put(COLUMN_ACTION, Integer.toString(rule.action.ordinal())); storageSource.insertRow(TABLE_NAME, entry); + + + + U64 singleRuleMask = AppCookie.getAppFieldMask().or(AppCookie.getUserFieldMask()); + List<Masked<U64>> changes = new ArrayList<Masked<U64>>(); + Iterator<FirewallRule> iter = this.rules.iterator(); + while (iter.hasNext()) { + FirewallRule r = iter.next(); + if (r.priority >= rule.priority) { + // + changes.add(Masked.of(AppCookie.makeCookie(APP_ID, r.ruleid), singleRuleMask)); + } + } + changes.add(Masked.of(RULE_MISS_COOKIE, singleRuleMask)); + routingService.handleRoutingDecisionChange(changes); + } @Override @@ -439,6 +471,19 @@ IFloodlightModule { } // delete from database storageSource.deleteRow(TABLE_NAME, Integer.toString(ruleid)); + + //Add announcement that the rule has been deleted + Masked<U64> delDescriptor = Masked.of( + AppCookie.makeCookie(APP_ID, ruleid), + AppCookie.getAppFieldMask().or(AppCookie.getUserFieldMask())); + + List<Masked<U64>> changes = new ArrayList<Masked<U64>>(); + changes.add(delDescriptor); + + //Add announcement that rule is added + // should we try to delete the flow even if not found in this.rules + routingService.handleRoutingDecisionChange(changes); + } /** diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index f2d86cba2de71bb0208d6c24413dc30561d463aa..14d7271348cf1dc91429740842129c1081fa3469 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -51,6 +51,7 @@ import net.floodlightcontroller.packet.TCP; import net.floodlightcontroller.packet.UDP; import net.floodlightcontroller.routing.ForwardingBase; import net.floodlightcontroller.routing.IRoutingDecision; +import net.floodlightcontroller.routing.IRoutingDecisionChangedListener; import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.topology.ITopologyService; @@ -87,7 +88,7 @@ import org.projectfloodlight.openflow.types.VlanVid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Forwarding extends ForwardingBase implements IFloodlightModule, IOFSwitchListener, ILinkDiscoveryListener { +public class Forwarding extends ForwardingBase implements IFloodlightModule, IOFSwitchListener, ILinkDiscoveryListener, IRoutingDecisionChangedListener { protected static Logger log = LoggerFactory.getLogger(Forwarding.class); final static U64 DEFAULT_FORWARDING_COOKIE = AppCookie.makeCookie(FORWARDING_APP_ID, 0); @@ -160,6 +161,13 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule, IOF return AppCookie.makeCookie(FORWARDING_APP_ID, user_fields); } + /** Called when the handleDecisionChange is triggered by an event (routing decision was changed in firewall). + * + * @param eventDescriptors Collection of descriptors that should be deleted from the switch.*/ + public void routingDecisionChanged(Iterable<Masked<U64>> eventDescriptors) { + deleteFlowsByDescriptor(eventDescriptors); + } + /** * Converts a sequence of masked IRoutingDecision descriptors into masked Forwarding cookies. * @@ -627,6 +635,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule, IOF public void startUp(FloodlightModuleContext context) { super.startUp(); switchService.addOFSwitchListener(this); + routingEngineService.addRoutingDecisionChangedListener(this); /* Register only if we want to remove stale flows */ if (REMOVE_FLOWS_ON_LINK_OR_PORT_DOWN) { @@ -634,6 +643,10 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule, IOF } } + + + + @Override public void switchAdded(DatapathId switchId) { } diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java index bd69e302f987c77fde08b2b0ed852de020654af4..2c4b7599b4fc5d5751033622a578bcf8d036c3a7 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java @@ -338,7 +338,7 @@ IFloodlightModule, IInfoProvider { byte[] srcMac = ofpPort.getHwAddr().getBytes(); byte[] zeroMac = { 0, 0, 0, 0, 0, 0 }; if (Arrays.equals(srcMac, zeroMac)) { - log.warn("Port {}/{} has zero hareware address" + log.warn("Port {}/{} has zero hardware address" + "overwrite with lower 6 bytes of dpid", dpid.toString(), ofpPort.getPortNo().getPortNumber()); System.arraycopy(dpidArray, 2, srcMac, 0, 6); diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java index 6d3b67f8e9fda5538b89cc938fb46c0ac917d252..592623fb89b63a758d119833833c9078ac27b67b 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java @@ -66,4 +66,5 @@ public interface IRoutingDecision { public void setHardTimeout(short hardTimeout); public U64 getDescriptor(); public void setDescriptor(U64 descriptor); + } diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingDecisionChangedListener.java b/src/main/java/net/floodlightcontroller/routing/IRoutingDecisionChangedListener.java new file mode 100644 index 0000000000000000000000000000000000000000..0f7fc52c28c3311f007a85eb2607cfcc2a2b84aa --- /dev/null +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingDecisionChangedListener.java @@ -0,0 +1,10 @@ +package net.floodlightcontroller.routing; + +import org.projectfloodlight.openflow.types.Masked; +import org.projectfloodlight.openflow.types.U64; + +public interface IRoutingDecisionChangedListener { + + public void routingDecisionChanged(Iterable<Masked<U64>> event); + +} diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java index fde607b89cef1ca00a78e8867748c0c2f4c2c795..faf1dba836bca96c7bec26fdaceb22a30014383b 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java @@ -20,6 +20,7 @@ package net.floodlightcontroller.routing; import java.util.ArrayList; import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.Masked; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.U64; @@ -82,5 +83,20 @@ public interface IRoutingService extends IFloodlightService { * or not have tunnels as part of the path. */ public boolean routeExists(DatapathId src, DatapathId dst, boolean tunnelEnabled); + + /** Register the RDCListener + * @param listener - The module that wants to listen for events + * */ + public void addRoutingDecisionChangedListener(IRoutingDecisionChangedListener listener); + + /** Remove the RDCListener + * @param listener - The module that wants to stop listening for events + * */ + public void removeRoutingDecisionChangedListener(IRoutingDecisionChangedListener listener); + + /** Handles what the listener actually does + * @param + * */ + public void handleRoutingDecisionChange(Iterable<Masked<U64>> event/* IRoutingDecisionChange event */); } diff --git a/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java index 8ce5c5c9415fcd14a3dcd34de0264b719b5536f7..9371528dc6f2b8aa5cd0c3f5fc49f37d6f0c81d3 100644 --- a/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java +++ b/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java @@ -136,4 +136,5 @@ public class RoutingDecision implements IRoutingDecision { " wildcard " + ((match == null) ? null : match.toString()); } + } diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java index 09c023e4f2fac5d824553b93ad9e1de4e0832bdb..85ae92b2dfb4e1a828c2527906597356df7ffa37 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java @@ -59,6 +59,7 @@ import net.floodlightcontroller.packet.BSN; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.LLDP; import net.floodlightcontroller.restserver.IRestApiService; +import net.floodlightcontroller.routing.IRoutingDecisionChangedListener; import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Route; @@ -73,6 +74,7 @@ import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.protocol.action.OFAction; import org.projectfloodlight.openflow.protocol.match.MatchField; import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.Masked; import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.U64; @@ -176,6 +178,9 @@ public class TopologyManager implements IFloodlightModule, ITopologyService, IRo * Topology Event Updater */ protected IEventCategory<TopologyEvent> eventCategory; + + /** Array list that contains all of the decisionChangedListeners */ + protected ArrayList<IRoutingDecisionChangedListener> decisionChangedListeners; /** * Topology Information exposed for a Topology related event - used inside @@ -854,6 +859,7 @@ public class TopologyManager implements IFloodlightModule, ITopologyService, IRo topologyAware = new ArrayList<ITopologyListener>(); ldUpdates = new LinkedBlockingQueue<LDUpdate>(); haListener = new HAListenerDelegate(); + this.decisionChangedListeners = new ArrayList<IRoutingDecisionChangedListener>(); registerTopologyDebugCounters(); registerTopologyDebugEvents(); } @@ -1531,4 +1537,19 @@ public class TopologyManager implements IFloodlightModule, ITopologyService, IRo return ports; } + + public void addRoutingDecisionChangedListener(IRoutingDecisionChangedListener listener) { + decisionChangedListeners.add(listener); + } + + public void removeRoutingDecisionChangedListener(IRoutingDecisionChangedListener listener) { + decisionChangedListeners.remove(listener); + } + + public void handleRoutingDecisionChange(Iterable<Masked<U64>> event) { + for(IRoutingDecisionChangedListener listener : decisionChangedListeners) { + listener.routingDecisionChanged(event); + } + } + }