diff --git a/src/main/java/net/floodlightcontroller/core/ControllerId.java b/src/main/java/net/floodlightcontroller/core/ControllerId.java new file mode 100644 index 0000000000000000000000000000000000000000..6fd347b234219ae4bee0b36923d5cf3893018b0c --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/ControllerId.java @@ -0,0 +1,61 @@ +package net.floodlightcontroller.core; + +import org.sdnplatform.sync.ISyncService; +import org.sdnplatform.sync.internal.config.ClusterConfig; + +import com.google.common.base.Optional; + +/** This class represents a unique id of this controller node. It is derived from + * the node id as returned by {@link ISyncService#getLocalNodeId()}. + * <p> + * Note that the unconfigured Node Id is not supported. Users are encouraged to + * represent an unconfigured Controller Node by {@link Optional#absent()}. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class ControllerId { + private final short nodeId; + + private ControllerId(short nodeId) { + if(nodeId == ClusterConfig.NODE_ID_UNCONFIGURED) + throw new IllegalArgumentException("nodeId is unconfigured"); + + this.nodeId = nodeId; + } + + public short getNodeId() { + return nodeId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + nodeId; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ControllerId other = (ControllerId) obj; + if (nodeId != other.nodeId) + return false; + return true; + } + + @Override + public String toString() { + return Short.toString(nodeId); + } + + public static ControllerId of(short nodeId) { + return new ControllerId(nodeId); + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/Deliverable.java b/src/main/java/net/floodlightcontroller/core/Deliverable.java new file mode 100644 index 0000000000000000000000000000000000000000..c82f31d85bd2ffab1567ac8fee25a926315f77b7 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/Deliverable.java @@ -0,0 +1,38 @@ +package net.floodlightcontroller.core; + +/** + * abstracts the 'back side' of a Future that is being listened on, i.e., an + * object that receives a result or an error of the computaton once it is ready. + * A deliverable can accept multiple computation results, indicated by the + * return value of deliver. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + * @param <T> + * type of the result of the computation + */ +public interface Deliverable<T> { + public static enum Status { + DONE, + CONTINUE + } + + /** + * deliver the result after a successful computation has completed + * + * @param msg + * result + * @return whether the delivery is complete with this result. + **/ + public void deliver(T msg); + + /** deliver an error result for the computation + * @param cause throwable that describes the error + */ + void deliverError(Throwable cause); + + /** whether or not the deliverable has been completed before. + */ + boolean isDone(); + + boolean cancel(boolean mayInterruptIfRunning); +} diff --git a/src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java b/src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java new file mode 100644 index 0000000000000000000000000000000000000000..1e724ac51819fc6a52d26a649ded028f0bd917cf --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java @@ -0,0 +1,22 @@ +package net.floodlightcontroller.core; + +import com.google.common.util.concurrent.AbstractFuture; + +/** Implementation of a ListenableFuture that provides a Deliverable interface to + * the provider. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + * @see Deliverable + * @param <T> + */ +public class DeliverableListenableFuture<T> extends AbstractFuture<T> implements Deliverable<T> { + @Override + public void deliver(final T result) { + set(result); + } + + @Override + public void deliverError(final Throwable cause) { + setException(cause); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/GenTableMap.java b/src/main/java/net/floodlightcontroller/core/GenTableMap.java new file mode 100644 index 0000000000000000000000000000000000000000..ef32a19796dfc977183fe39cf8f55fdf5049a6cb --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/GenTableMap.java @@ -0,0 +1,136 @@ +package net.floodlightcontroller.core; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.Immutable; + +import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsEntry; +import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsReply; +import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsRequest; +import org.projectfloodlight.openflow.types.GenTableId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableMap; + +/** A registry for GenTables. Initialized during switch handshake, based on a + * {@link OFBsnGentableDescStatsRequest}. The table for a particular switch + * can be retrieved via {@link IOFSwitch#getGenTableMap()}. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +@Immutable +public class GenTableMap { + private static final Logger logger = LoggerFactory.getLogger(GenTableMap.class); + + private final Map<GenTableId, OFBsnGentableDescStatsEntry> idMap; + private final Map<String, OFBsnGentableDescStatsEntry> nameMap; + + // an empty gentable map + private GenTableMap() { + idMap = ImmutableMap.of(); + nameMap = ImmutableMap.of(); + } + + public GenTableMap(Iterable<OFBsnGentableDescStatsEntry> entries) { + // note: not using an ImmutableMap.Builder here, because we need to + // check for duplicates + Map<GenTableId, OFBsnGentableDescStatsEntry> idBuildMap = new LinkedHashMap<>(); + Map<String, OFBsnGentableDescStatsEntry> nameBuildMap = new LinkedHashMap<>(); + + for (OFBsnGentableDescStatsEntry e : entries) { + GenTableId id = e.getTableId(); + String name = e.getName(); + if (idBuildMap.containsKey(id)) { + logger.warn("Duplicate table id " + id + " - entry {} present. Ignoring new entry {}", + idBuildMap.get(id), e); + continue; + } + if (nameBuildMap.containsKey(name)) { + logger.warn( + "Duplicate table name " + name + " - entry named {} present. Ignoring new entry {}", + nameBuildMap.get(name), e); + continue; + } + idBuildMap.put(id, e); + nameBuildMap.put(name, e); + } + this.idMap = ImmutableMap.copyOf(idBuildMap); + this.nameMap = ImmutableMap.copyOf(nameBuildMap); + } + + public Set<GenTableId> getIds() { + return idMap.keySet(); + } + + public Set<String> getNames() { + return nameMap.keySet(); + } + + public Collection<OFBsnGentableDescStatsEntry> getEntries() { + return idMap.values(); + } + + public boolean hasEntry(GenTableId id) { + return idMap.containsKey(id); + } + + /** retrieve a GenTable Description from the map by id. + * + * @param id + * @return the retrieved gen table description. + * @throws GenTableNotFoundException if no gentable with the given id was found in the map + */ + @Nonnull + public OFBsnGentableDescStatsEntry getEntry(GenTableId id) throws GenTableNotFoundException { + OFBsnGentableDescStatsEntry entry = idMap.get(id); + if(entry == null) + throw new GenTableNotFoundException(id, idMap.values()); + return entry; + } + + public boolean hasEntry(String name) { + return nameMap.containsKey(name); + } + + /** retrieve a GenTable Description from the map by name. + * + * @param name + * @return the retrieved gen table description. + * @throws GenTableNotFoundException if no gentable with the given name was found in the map + */ + @Nonnull + public OFBsnGentableDescStatsEntry getEntry(String name) throws GenTableNotFoundException { + OFBsnGentableDescStatsEntry entry = nameMap.get(name); + if(entry == null) + throw new GenTableNotFoundException(name, nameMap.values()); + return entry; + } + + public final static GenTableMap empty() { + return new GenTableMap(); + } + + public static GenTableMap of(Iterable<OFBsnGentableDescStatsReply> replies) { + List<OFBsnGentableDescStatsEntry> allEntries = new ArrayList<>(); + for(OFBsnGentableDescStatsReply reply: replies) { + allEntries.addAll(reply.getEntries()); + } + return new GenTableMap(allEntries); + } + + @Override + public String toString() { + return idMap.toString(); + } + + public int size() { + return idMap.size(); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java b/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..544fc1e8488a0fa33ee934be31d3d6e03ce64ca2 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java @@ -0,0 +1,44 @@ +package net.floodlightcontroller.core; + +import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsEntry; +import org.projectfloodlight.openflow.types.GenTableId; + +/** A GenTable was not found in the {@link GenTableMap}. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class GenTableNotFoundException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public GenTableNotFoundException(String name, Iterable<OFBsnGentableDescStatsEntry> available) { + super(getMessageForName(name, available)); + } + + private static String getMessageForName(String name, + Iterable<OFBsnGentableDescStatsEntry> available) { + return String.format("Table not found: %s (available tables: %s)", name, availableDescr(available)); + } + + public GenTableNotFoundException(GenTableId id, Iterable<OFBsnGentableDescStatsEntry> available) { + super(getMessageForId(id, available)); + } + + private static String getMessageForId(GenTableId id, + Iterable<OFBsnGentableDescStatsEntry> available) { + return String.format("Table not found: %s (available tables: %s)", id, availableDescr(available)); + } + + private static String availableDescr(Iterable<OFBsnGentableDescStatsEntry> available) { + StringBuilder b = new StringBuilder(); + boolean first = true; + for(OFBsnGentableDescStatsEntry e: available) { + if(!first) + b.append(", "); + first = false; + b.append(e.getName()).append("=").append(e.getTableId()); + } + return b.toString(); + } + + +} diff --git a/src/main/java/net/floodlightcontroller/core/HARole.java b/src/main/java/net/floodlightcontroller/core/HARole.java new file mode 100644 index 0000000000000000000000000000000000000000..0c2886f1e179579fc0b011317cdf8362a95cab9f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/HARole.java @@ -0,0 +1,88 @@ +package net.floodlightcontroller.core; + +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * HARole describes the role that a given controller node currently plays in the + * management of the SDN network. Controller nodes can be either + * <ul> + * <li>ACTIVE - currently controlling the network + * <li>STANDBY - standing by in case of a fail-over from the ACTIVE node + * </ul> + * At any given time there SHOULD be at most one ACTIVE node in the network + * (this invariant cannot be strictly guranteed for certain split-brain + * situtations). There can be multiple STANDBY controllers. There are other + * HA-related roles in the system. Try to not confuse them. + * <ul> + * <li>On the cluster management/bigsync layer {@link ISyncService} determines a + * DOMAIN LEADER / DOMAIN FOLLOWER (which are exposed via + * <li>On the OF layer, switch connections can be in either MASTER, SLAVE or + * EQUAL {@link Role} (exposed by {@link IOFSwitchListener}). + * </ul> + * Most applications and modules trying to decide something on the ACTIVE node + * should base that decision on the HARole. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public enum HARole { + /** This controller node is currently actively managing the SDN network. At any given + * time, there should be at most one ACTIVE node. When the ACTIVE node fails, a STANDBY + * node is determined to become ACTIVE. + */ + ACTIVE(OFControllerRole.ROLE_MASTER), + + /** This controller node is currently standing by and not managing the networking. There + * may be more than one STANDBY nodes in the network. + */ + STANDBY(OFControllerRole.ROLE_SLAVE); + + private static final Logger logger = LoggerFactory.getLogger(HARole.class); + private final OFControllerRole ofRole; + + HARole(OFControllerRole ofRole) { + this.ofRole = ofRole; + } + + /** a backwards-compatible {@link #valueOf} that accepts the old terms "MASTER" and "SLAVE" + * and normalizes them to ACTIVE and STANDBY. + * + * @param roleString + * @return an HARole + * @throws IllegalArgumentException - if no such role can be found. + */ + public static HARole valueOfBackwardsCompatible(String roleString) throws IllegalArgumentException { + roleString = roleString.trim().toUpperCase(); + if("MASTER".equals(roleString)) { + logger.warn("got legacy role name MASTER - normalized to ACTIVE", roleString); + if(logger.isDebugEnabled()) { + logger.debug("Legacy role call stack", new IllegalArgumentException()); + } + roleString = "ACTIVE"; + } else if ("SLAVE".equals(roleString)) { + logger.warn("got legacy role name SLAVE - normalized to STANDBY", roleString); + if(logger.isDebugEnabled()) { + logger.debug("Legacy role call stack", new IllegalArgumentException()); + } + roleString = "STANDBY"; + } + return valueOf(roleString); + } + + public OFControllerRole getOFRole() { + return ofRole; + } + + public static HARole ofOFRole(OFControllerRole role) { + switch(role) { + case ROLE_MASTER: + case ROLE_EQUAL: + return ACTIVE; + case ROLE_SLAVE: + return STANDBY; + default: + throw new IllegalArgumentException("Unmappable controller role: " + role); + } + } +} diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java index c0aa1fd6d5faa9426c7580d7e02fc685c0a96021..ce3e1786f90660064f7cc0e8e0ed6b634670ce5d 100644 --- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java +++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java @@ -17,8 +17,6 @@ package net.floodlightcontroller.core; -import java.util.HashMap; - import java.util.List; import java.util.Set; import java.util.Map; @@ -26,11 +24,22 @@ import java.util.Map; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.packet.Ethernet; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.vendor.nicira.OFRoleVendorData; - +import org.jboss.netty.util.Timer; + +import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.HARole; +import net.floodlightcontroller.core.IHAListener; +import net.floodlightcontroller.core.IInfoProvider; +import net.floodlightcontroller.core.IOFMessageListener; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.RoleInfo; +import net.floodlightcontroller.core.internal.RoleManager; +import net.floodlightcontroller.core.internal.Controller.IUpdate; +import net.floodlightcontroller.core.internal.Controller.ModuleLoaderState; + +import net.floodlightcontroller.core.FloodlightContextStore; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFType; /** * The interface exposed by the core bundle that allows you to interact * with connected switches. @@ -45,38 +54,7 @@ public interface IFloodlightProviderService extends * representation of the payload of a packet-in message. */ public static final String CONTEXT_PI_PAYLOAD = - "net.floodlightcontroller.core.IFloodlightProvider.piPayload"; - - /** - * The role of the controller as used by the OF 1.2 and OVS failover and - * load-balancing mechanism. - */ - public static enum Role { - EQUAL(OFRoleVendorData.NX_ROLE_OTHER), - MASTER(OFRoleVendorData.NX_ROLE_MASTER), - SLAVE(OFRoleVendorData.NX_ROLE_SLAVE); - - private final int nxRole; - - private Role(int nxRole) { - this.nxRole = nxRole; - } - - private static Map<Integer,Role> nxRoleToEnum - = new HashMap<Integer,Role>(); - static { - for(Role r: Role.values()) - nxRoleToEnum.put(r.toNxRole(), r); - } - public int toNxRole() { - return nxRole; - } - // Return the enum representing the given nxRole or null if no - // such role exists - public static Role fromNxRole(int nxRole) { - return nxRoleToEnum.get(nxRole); - } - }; + "org.projectfloodlight.core.IFloodlightProvider.piPayload"; /** * A FloodlightContextStore object that can be used to retrieve the @@ -85,6 +63,15 @@ public interface IFloodlightProviderService extends public static final FloodlightContextStore<Ethernet> bcStore = new FloodlightContextStore<Ethernet>(); + /** + * Service name used in the service directory representing + * the OpenFlow controller-switch channel + * + * @see ILocalServiceAddressTracker + * @see IClusterServiceAddressDirectory + */ + public static final String SERVICE_DIRECTORY_SERVICE_NAME = "openflow"; + /** * Adds an OpenFlow message listener * @param type The OFType the component wants to listen for @@ -106,77 +93,52 @@ public interface IFloodlightProviderService extends public Map<OFType, List<IOFMessageListener>> getListeners(); /** - * If the switch with the given DPID is known to any controller in the - * cluster, this method returns the associated IOFSwitch instance. As such - * the returned switches not necessarily connected or in master role for - * the local controller. - * - * Multiple calls to this method with the same DPID may return different - * IOFSwitch references. A caller must not store or otherwise rely on - * IOFSwitch references to be constant over the lifecycle of a switch. - * - * @param dpid the dpid of the switch to query - * @return the IOFSwitch instance associated with the dpid, null if no - * switch with the dpid is known to the cluster + * Get the current role of the controller */ - public IOFSwitch getSwitch(long dpid); + public HARole getRole(); /** - * Returns a snapshot of the set DPIDs for all known switches. - * - * The returned set is owned by the caller: the caller can modify it at - * will and changes to the known switches are not reflected in the returned - * set. The caller needs to call getAllSwitchDpids() if an updated - * version is needed. - * - * See {@link #getSwitch(long)} for what "known" switch is. - * @return the set of DPIDs of all known switches + * Get the current role of the controller */ - public Set<Long> getAllSwitchDpids(); + public RoleInfo getRoleInfo(); /** - * Return a snapshot - * FIXME: asdf - * @return + * Get the current mapping of controller IDs to their IP addresses + * Returns a copy of the current mapping. + * @see IHAListener */ - public Map<Long,IOFSwitch> getAllSwitchMap(); + public Map<String,String> getControllerNodeIPs(); /** - * Get the current role of the controller + * Gets the ID of the controller */ - public Role getRole(); + public String getControllerId(); /** - * Get the current role of the controller + * Gets the controller hostname + * @return the controller hostname */ - public RoleInfo getRoleInfo(); + public String getOFHostname(); /** - * Get the current mapping of controller IDs to their IP addresses - * Returns a copy of the current mapping. - * @see IHAListener + * Gets the controller's openflow port + * @return the controller's openflow port */ - public Map<String,String> getControllerNodeIPs(); - + public int getOFPort(); /** * Set the role of the controller * @param role The new role for the controller node * @param changeDescription The reason or other information for this role change */ - public void setRole(Role role, String changeDescription); - - /** - * Add a switch listener - * @param listener The module that wants to listen for events - */ - public void addOFSwitchListener(IOFSwitchListener listener); + public void setRole(HARole role, String changeDescription); /** - * Remove a switch listener - * @param listener The The module that no longer wants to listen for events + * Add an update task for asynchronous, serialized execution + * + * @param update */ - public void removeOFSwitchListener(IOFSwitchListener listener); + public void addUpdateToQueue(IUpdate update); /** * Adds a listener for HA role events @@ -190,53 +152,13 @@ public interface IFloodlightProviderService extends */ public void removeHAListener(IHAListener listener); - /** - * Add a listener for ready-for-flow-reconcile events - * @param l - */ - public void addReadyForReconcileListener(IReadyForReconcileListener l); - - /** - * Terminate the process - */ - public void terminate(); - - /** - * Re-injects an OFMessage back into the packet processing chain - * @param sw The switch to use for the message - * @param msg the message to inject - * @return True if successfully re-injected, false otherwise - * @throws NullPointerException if switch or msg is null - */ - public boolean injectOfMessage(IOFSwitch sw, OFMessage msg); - - /** - * Re-injects an OFMessage back into the packet processing chain - * @param sw The switch to use for the message - * @param msg the message to inject - * @param bContext a floodlight context to use if required. Can be null - * @return True if successfully re-injected, false otherwise - * @throws NullPointerException if switch or msg is null - */ - public boolean injectOfMessage(IOFSwitch sw, OFMessage msg, - FloodlightContext bContext); - /** * Process written messages through the message listeners for the controller * @param sw The switch being written to * @param m the message - * @param bc any accompanying context object. Can be null in which case a - * new context will be allocated and passed to listeners * @throws NullPointerException if switch or msg is null */ - public void handleOutgoingMessage(IOFSwitch sw, OFMessage m, - FloodlightContext bc); - - /** - * Gets the BasicFactory - * @return an OpenFlow message factory - */ - public BasicFactory getOFMessageFactory(); + public void handleOutgoingMessage(IOFSwitch sw, OFMessage m); /** * Run the main I/O loop of the Controller. @@ -265,21 +187,12 @@ public interface IFloodlightProviderService extends */ public Map<String, Object> getControllerInfo(String type); - /** * Return the controller start time in milliseconds * @return */ public long getSystemStartTime(); - /** - * Configure controller to always clear the flow table on the switch, - * when it connects to controller. This will be true for first time switch - * reconnect, as well as a switch re-attaching to Controller after HA - * switch over to ACTIVE role - */ - public void setAlwaysClearFlowsOnSwActivate(boolean value); - /** * Get controller memory information */ @@ -292,30 +205,38 @@ public interface IFloodlightProviderService extends public Long getUptime(); /** - * Adds an OFSwitch driver - * @param manufacturerDescriptionPrefix Register the given prefix - * with the driver. - * @param driver A IOFSwitchDriver instance to handle IOFSwitch instaniation - * for the given manufacturer description prefix - * @throws IllegalStateException If the the manufacturer description is - * already registered - * @throws NullPointerExeption if manufacturerDescriptionPrefix is null - * @throws NullPointerExeption if driver is null + * Get the set of port prefixes that will define an UPLINK port. + * @return The set of prefixes */ - public void addOFSwitchDriver(String desc, IOFSwitchDriver driver); + public Set<String> getUplinkPortPrefixSet(); + + + public void handleMessage(IOFSwitch sw, OFMessage m, + FloodlightContext bContext); /** - * Record a switch event in in-memory debug-event - * @param switchDPID - * @param reason Reason for this event - * @param flushNow see debug-event flushing in IDebugEventService + * Gets a hash wheeled timer to be used for for timeout scheduling + * @return a hash wheeled timer */ - public void addSwitchEvent(long switchDPID, String reason, boolean flushNow); + public Timer getTimer(); /** - * Get the set of port prefixes that will define an UPLINK port. - * @return The set of prefixes + * Gets the role manager + * @return the role manager */ - public Set<String> getUplinkPortPrefixSet(); + public RoleManager getRoleManager(); + + /** + * Gets the current module loading state. + * @return the current module loading state. + */ + ModuleLoaderState getModuleLoaderState(); + + /** + * Gets the current number of worker threads + * @return Used for netty setup + */ + public int getWorkerThreads(); } + diff --git a/src/main/java/net/floodlightcontroller/core/IHAListener.java b/src/main/java/net/floodlightcontroller/core/IHAListener.java deleted file mode 100644 index 2ffe82fd586b1012f29c24d397eb6c212a5aa02e..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/IHAListener.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core; - -import java.util.Map; - -public interface IHAListener extends IListener<HAListenerTypeMarker> { - - /** - * This notification is fired if the controller's initial role was SLAVE - * and the controller is now transitioning to MASTER. - * Modules need to read their initial role in startUp from floodlight - * provider. - */ - public void transitionToMaster(); - - /** - * Gets called when the IP addresses of the controller nodes in the - * controller cluster change. All parameters map controller ID to - * the controller's IP. - * - * @param curControllerNodeIPs The current mapping of controller IDs to IP - * @param addedControllerNodeIPs These IPs were added since the last update - * @param removedControllerNodeIPs These IPs were removed since the last update - */ - public void controllerNodeIPsChanged( - Map<String, String> curControllerNodeIPs, - Map<String, String> addedControllerNodeIPs, - Map<String, String> removedControllerNodeIPs - ); -} diff --git a/src/main/java/net/floodlightcontroller/core/IOFConnection.java b/src/main/java/net/floodlightcontroller/core/IOFConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..a14021fbd47b087495b57bdd3b1736966df0a798 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/IOFConnection.java @@ -0,0 +1,62 @@ +package net.floodlightcontroller.core; + +import java.net.SocketAddress; + +import java.util.Date; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFAuxId; + + +/** Contract for an openflow connection to a switch. + * Provides message write and request/response handling capabilities. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public interface IOFConnection extends IOFMessageWriter { + + /** + * Retrieves the date the connection connected to this controller + * @return the date + */ + Date getConnectedSince(); + + /** + * Flush all flows queued for this switch in the current thread. + * NOTE: The contract is limited to the current thread + */ + void flush(); + + /** @return the DatapathId of the switch associated with the connection */ + DatapathId getDatapathId(); + + /** @return the OFAuxId of the this connection */ + OFAuxId getAuxId(); + + /** + * Get the IP address of the remote (switch) end of the connection + * @return the inet address + */ + SocketAddress getRemoteInetAddress(); + + /** + * Get the IP address of the local end of the connection + * + * @return the inet address + */ + SocketAddress getLocalInetAddress(); + + /** + * Get's the OFFactory that this connection was constructed with. + * This is the factory that was found in the features reply during + * the channel handshake + * @return The connection's OFFactory + */ + OFFactory getOFFactory(); + + /** @return whether this connection is currently (still) connected to the controller. + */ + boolean isConnected(); + + +} diff --git a/src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java b/src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java new file mode 100644 index 0000000000000000000000000000000000000000..0ec7a9e1b2b081b34c813d5d9dd959028e1e49cc --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java @@ -0,0 +1,23 @@ +package net.floodlightcontroller.core; + +import net.floodlightcontroller.core.internal.IOFConnectionListener; + +public interface IOFConnectionBackend extends IOFConnection { + /** + * Disconnect the channel + */ + void disconnect(); + + /** + * Cancel all pending request + */ + void cancelAllPendingRequests(); + + /** @return whether the output stream associated with this connection + * is currently writeable (for throttling) + */ + boolean isWritable(); + + /** set the message/closing listener for this connection */ + void setListener(IOFConnectionListener listener); +} diff --git a/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java b/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java index 00fdac1f99379ee8aa1e5dfee00de6bd4da9a4f1..1fe71529c9e64d364c92a0d2255083169a737dc8 100644 --- a/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java +++ b/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java @@ -17,8 +17,8 @@ package net.floodlightcontroller.core; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFType; /** * diff --git a/src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java b/src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..bd27181f19e9170fac71db1557942dcc8cef0510 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java @@ -0,0 +1,79 @@ +/** +* Copyright 2011, Big Switch Networks, Inc. +* Originally created by David Erickson, Stanford University +* +* 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.core; + +import java.util.List; + +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFRequest; +import org.projectfloodlight.openflow.protocol.OFStatsReply; +import org.projectfloodlight.openflow.protocol.OFStatsRequest; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * An interface to describe classes that write OF messages. + * E.g. IOFSwitch, IOFConnection + */ + +public interface IOFMessageWriter{ + + /** + * Writes to the OFMessage to the output stream. + * + * <p><b>Note:</b> this method has fire-and-forget semantics. When the connection is + * not currently connected, it will silently discard the messages. + * + * @param m + */ + void write(OFMessage m); + + /** + * Writes the list of messages to the output stream. + * + * <p><b>Note:</b> this method has fire-and-forget semantics. When the connection is + * not currently connected, it will silently discard the messages. + * + * @param msglist + */ + void write(Iterable<OFMessage> msglist); + + /** write an OpenFlow Request message, register for a single corresponding reply message + * or error message. + * + * @param request + * @return a Future object that can be used to retrieve the asynchrounous + * response when available. + * + * If the connection is not currently connected, will + * return a Future that immediately fails with a @link{SwitchDisconnectedException}. + */ + <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request); + + /** write a Stats (Multipart-) request, register for all corresponding reply messages. + * Returns a Future object that can be used to retrieve the List of asynchronous + * OFStatsReply messages when it is available. + * + * @param request stats request + * @return Future object wrapping OFStatsReply + * If the connection is not currently connected, will + * return a Future that immediately fails with a @link{SwitchDisconnectedException}. + */ + <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest( + OFStatsRequest<REPLY> request); +} diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java deleted file mode 100644 index fb27460401007cdc639d4c8ee38cc73101ce0c40..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java +++ /dev/null @@ -1,669 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core; - -import java.io.IOException; -import java.net.SocketAddress; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Future; -import net.floodlightcontroller.core.IFloodlightProviderService.Role; -import net.floodlightcontroller.core.internal.Controller; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException; -import net.floodlightcontroller.threadpool.IThreadPoolService; -import net.floodlightcontroller.util.OrderedCollection; - -import org.jboss.netty.channel.Channel; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPortStatus; -import org.openflow.protocol.OFStatisticsReply; -import org.openflow.protocol.OFStatisticsRequest; -import org.openflow.protocol.statistics.OFDescriptionStatistics; -import org.openflow.protocol.statistics.OFStatistics; - -/** - * - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface IOFSwitch { - // Attribute keys - public static final String SWITCH_DESCRIPTION_FUTURE = "DescriptionFuture"; - public static final String SWITCH_SUPPORTS_NX_ROLE = "supportsNxRole"; - public static final String SWITCH_IS_CORE_SWITCH = "isCoreSwitch"; - public static final String PROP_FASTWILDCARDS = "FastWildcards"; - public static final String PROP_REQUIRES_L3_MATCH = "requiresL3Match"; - public static final String PROP_SUPPORTS_OFPP_TABLE = "supportsOfppTable"; - public static final String PROP_SUPPORTS_OFPP_FLOOD = "supportsOfppFlood"; - public static final String PROP_SUPPORTS_NETMASK_TBL = "supportsNetmaskTbl"; - - public enum OFPortType { - NORMAL("normal"), // normal port (default) - TUNNEL("tunnel"), // tunnel port - UPLINK("uplink"), // uplink port (on a virtual switch) - MANAGEMENT("management"), // for in-band management - TUNNEL_LOOPBACK("tunnel-loopback"); - - private final String value; - OFPortType(String v) { - value = v; - } - - @Override - public String toString() { - return value; - } - - public static OFPortType fromString(String str) { - for (OFPortType m : OFPortType.values()) { - if (m.value.equals(str)) { - return m; - } - } - return OFPortType.NORMAL; - } - } - - /** - * Describes a change of an open flow port - */ - public static class PortChangeEvent { - public final ImmutablePort port; - public final PortChangeType type; - /** - * @param port - * @param type - */ - public PortChangeEvent(ImmutablePort port, - PortChangeType type) { - this.port = port; - this.type = type; - } - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((port == null) ? 0 : port.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - PortChangeEvent other = (PortChangeEvent) obj; - if (port == null) { - if (other.port != null) return false; - } else if (!port.equals(other.port)) return false; - if (type != other.type) return false; - return true; - } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "[" + type + " " + port.toBriefString() + "]"; - } - } - - /** - * the type of change that happened to an open flow port - */ - public enum PortChangeType { - ADD, OTHER_UPDATE, DELETE, UP, DOWN, - } - - /** - * Set IFloodlightProviderService for this switch instance - * Called immediately after instantiation - * - * @param controller - */ - public void setFloodlightProvider(Controller controller); - - /** - * Set IThreadPoolService for this switch instance - * Called immediately after instantiation - * - * @param threadPool - */ - public void setThreadPoolService(IThreadPoolService threadPool); - - /** - * Set debug counter service for per-switch counters - * Called immediately after instantiation - * @param debugCounters - * @throws CounterException - */ - public void setDebugCounterService(IDebugCounterService debugCounters) - throws CounterException; - - /** - * Set the netty Channel this switch instance is associated with - * Called immediately after instantiation - * - * @param channel - */ - public void setChannel(Channel channel); - - /** - * Called when OFMessage enters pipeline. Returning true cause the message - * to be dropped. - * @param ofm - * @return - */ - public boolean inputThrottled(OFMessage ofm); - - /** - * Return if the switch is currently overloaded. The definition of - * overload refers to excessive traffic in the control path, namely - * a high packet in rate. - * @return - */ - boolean isOverloaded(); - - /** - * Write OFMessage to the output stream, subject to switch rate limiting. - * The message will be handed to the floodlightProvider for possible filtering - * and processing by message listeners - * @param msg - * @param cntx - * @throws IOException - */ - public void writeThrottled(OFMessage msg, FloodlightContext cntx) throws IOException; - - /** - * Writes the list of messages to the output stream, subject to rate limiting. - * The message will be handed to the floodlightProvider for possible filtering - * and processing by message listeners. - * @param msglist - * @param bc - * @throws IOException - */ - void writeThrottled(List<OFMessage> msglist, FloodlightContext bc) - throws IOException; - - /** - * Writes to the OFMessage to the output stream, bypassing rate limiting. - * The message will be handed to the floodlightProvider for possible filtering - * and processing by message listeners - * @param m - * @param bc - * @throws IOException - */ - public void write(OFMessage m, FloodlightContext bc) throws IOException; - - /** - * Writes the list of messages to the output stream, bypassing rate limiting. - * The message will be handed to the floodlightProvider for possible filtering - * and processing by message listeners. - * @param msglist - * @param bc - * @throws IOException - */ - public void write(List<OFMessage> msglist, FloodlightContext bc) throws IOException; - - /** - * - * @throws IOException - */ - public void disconnectOutputStream(); - - /** - * Returns switch features from features Reply - * @return - */ - public int getBuffers(); - - public int getActions(); - - public int getCapabilities(); - - public byte getTables(); - - /** - * @return a copy of the description statistics for this switch - */ - public OFDescriptionStatistics getDescriptionStatistics(); - - /** - * Set the OFFeaturesReply message returned by the switch during initial - * handshake. - * @param featuresReply - */ - public void setFeaturesReply(OFFeaturesReply featuresReply); - - /** - * Get list of all enabled ports. This will typically be different from - * the list of ports in the OFFeaturesReply, since that one is a static - * snapshot of the ports at the time the switch connected to the controller - * whereas this port list also reflects the port status messages that have - * been received. - * @return Unmodifiable list of ports not backed by the underlying collection - */ - public Collection<ImmutablePort> getEnabledPorts(); - - /** - * Get list of the port numbers of all enabled ports. This will typically - * be different from the list of ports in the OFFeaturesReply, since that - * one is a static snapshot of the ports at the time the switch connected - * to the controller whereas this port list also reflects the port status - * messages that have been received. - * @return Unmodifiable list of ports not backed by the underlying collection - */ - public Collection<Short> getEnabledPortNumbers(); - - /** - * Retrieve the port object by the port number. The port object - * is the one that reflects the port status updates that have been - * received, not the one from the features reply. - * @param portNumber - * @return port object - */ - public ImmutablePort getPort(short portNumber); - - /** - * Retrieve the port object by the port name. The port object - * is the one that reflects the port status updates that have been - * received, not the one from the features reply. - * Port names are case insentive - * @param portName - * @return port object - */ - public ImmutablePort getPort(String portName); - - /** - * Add or modify a switch port. - * This is called by the core controller - * code in response to a OFPortStatus message. It should not typically be - * called by other floodlight applications. - * - * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow - * spec is not clear on whether portNames are portNumbers are considered - * authoritative identifiers. We treat portNames <-> portNumber mappings - * as fixed. If they change, we delete all previous conflicting ports and - * add all new ports. - * - * @param ps the port status message - * @return the ordered Collection of changes "applied" to the old ports - * of the switch according to the PortStatus message. A single PortStatus - * message can result in multiple changes. - * If portName <-> portNumber mappings have - * changed, the iteration order ensures that delete events for old - * conflicting appear before before events adding new ports - */ - public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps); - - /** - * Get list of all ports. This will typically be different from - * the list of ports in the OFFeaturesReply, since that one is a static - * snapshot of the ports at the time the switch connected to the controller - * whereas this port list also reflects the port status messages that have - * been received. - * @return Unmodifiable list of ports - */ - public Collection<ImmutablePort> getPorts(); - - /** - * @param portNumber - * @return Whether a port is enabled per latest port status message - * (not configured down nor link down nor in spanning tree blocking state) - */ - public boolean portEnabled(short portNumber); - - /** - * @param portNumber - * @return Whether a port is enabled per latest port status message - * (not configured down nor link down nor in spanning tree blocking state) - */ - public boolean portEnabled(String portName); - - /** - * Compute the changes that would be required to replace the old ports - * of this switch with the new ports - * @param ports new ports to set - * @return the ordered collection of changes "applied" to the old ports - * of the switch in order to set them to the new set. - * If portName <-> portNumber mappings have - * changed, the iteration order ensures that delete events for old - * conflicting appear before before events adding new ports - */ - public OrderedCollection<PortChangeEvent> - comparePorts(Collection<ImmutablePort> ports); - - /** - * Replace the ports of this switch with the given ports. - * @param ports new ports to set - * @return the ordered collection of changes "applied" to the old ports - * of the switch in order to set them to the new set. - * If portName <-> portNumber mappings have - * changed, the iteration order ensures that delete events for old - * conflicting appear before before events adding new ports - */ - public OrderedCollection<PortChangeEvent> - setPorts(Collection<ImmutablePort> ports); - - - /** - * Get the datapathId of the switch - * @return - */ - public long getId(); - - /** - * Get a string version of the ID for this switch - * @return - */ - public String getStringId(); - - /** - * Get the IP Address for the switch - * @return the inet address - */ - public SocketAddress getInetAddress(); - - /** - * Retrieves attributes of this switch - * @return - */ - public Map<Object, Object> getAttributes(); - - /** - * Retrieves the date the switch connected to this controller - * @return the date - */ - public Date getConnectedSince(); - - /** - * Returns the next available transaction id - * @return - */ - public int getNextTransactionId(); - - /** - * Returns a Future object that can be used to retrieve the asynchronous - * OFStatisticsReply when it is available. - * - * @param request statistics request - * @return Future object wrapping OFStatisticsReply - * @throws IOException - */ - public Future<List<OFStatistics>> queryStatistics(OFStatisticsRequest request) - - throws IOException; - - /** - * Returns a Future object that can be used to retrieve the asynchronous - * OFStatisticsReply when it is available. - * - * @param request statistics request - * @return Future object wrapping OFStatisticsReply - * @throws IOException - */ - public Future<OFFeaturesReply> querySwitchFeaturesReply() - throws IOException; - - /** - * Deliver the featuresReply future reply - * @param reply the reply to deliver - */ - void deliverOFFeaturesReply(OFMessage reply); - - /* - * Cancel features reply with a specific transction ID - * @param transactionId the transaction ID - */ - public void cancelFeaturesReply(int transactionId); - - /** - * Check if the switch is connected to this controller. Whether a switch - * is connected is independent of whether the switch is active - * @return whether the switch is still disconnected - */ - public boolean isConnected(); - - /** - * Check if the switch is active. I.e., the switch is connected to this - * controller and is in master role - * @return - */ - public boolean isActive(); - - /** - * Set whether the switch is connected - * @param connected whether the switch is connected - */ - public void setConnected(boolean connected); - - /** - * Get the current role of the controller for the switch - * @return the role of the controller - */ - public Role getHARole(); - - /** - * Set switch's HA role to role. The haRoleReplyReceived indicates - * if a reply was received from the switch (error replies excluded). - * - * If role is null, the switch should close the channel connection. - * - * @param role - * @param haRoleReplyReceived - */ - public void setHARole(Role role); - - /** - * Deliver the statistics future reply - * @param reply the reply to deliver - */ - public void deliverStatisticsReply(OFStatisticsReply reply); - - /** - * Cancel the statistics reply with the given transaction ID - * @param transactionId the transaction ID - */ - public void cancelStatisticsReply(int transactionId); - - /** - * Cancel all statistics replies - */ - public void cancelAllStatisticsReplies(); - - /** - * Checks if a specific switch property exists for this switch - * @param name name of property - * @return value for name - */ - boolean hasAttribute(String name); - - /** - * Set properties for switch specific behavior - * @param name name of property - * @return value for name - */ - Object getAttribute(String name); - - /** - * Check if the given attribute is present and if so whether it is equal - * to "other" - * @param name the name of the attribute to check - * @param other the object to compare the attribute against. - * @return true iff the specified attribute is set and equals() the given - * other object. - */ - boolean attributeEquals(String name, Object other); - - /** - * Set properties for switch specific behavior - * @param name name of property - * @param value value for name - */ - void setAttribute(String name, Object value); - - /** - * Set properties for switch specific behavior - * @param name name of property - * @return current value for name or null (if not present) - */ - Object removeAttribute(String name); - - /** - * Clear all flowmods on this switch - */ - public void clearAllFlowMods(); - - /** - * Update broadcast cache - * @param data - * @return true if there is a cache hit - * false if there is no cache hit. - */ - public boolean updateBroadcastCache(Long entry, Short port); - - /** - * Get the portBroadcastCacheHits - * @return - */ - public Map<Short, Long> getPortBroadcastHits(); - - /** - * Send a flow statistics request to the switch. This call returns after - * sending the stats. request to the switch. - * @param request flow statistics request message - * @param xid transaction id, must be obtained by using the getXid() API. - * @param caller the caller of the API. receive() callback of this - * caller would be called when the reply from the switch is received. - * @return the transaction id for the message sent to the switch. The - * transaction id can be used to match the response with the request. Note - * that the transaction id is unique only within the scope of this switch. - * @throws IOException - */ - public void sendStatsQuery(OFStatisticsRequest request, int xid, - IOFMessageListener caller) throws IOException; - - /** - * Flush all flows queued for this switch in the current thread. - * NOTE: The contract is limited to the current thread - */ - public void flush(); - - /*********************************************** - * The following method can be overridden by - * specific types of switches - *********************************************** - */ - - /** - * Set the SwitchProperties based on it's description - * @param description - */ - public void setSwitchProperties(OFDescriptionStatistics description); - - /** - * Return the type of OFPort - * @param port_num - * @return - */ - public OFPortType getPortType(short port_num); - - /** - * Can the port be turned on without forming a new loop? - * @param port_num - * @return - */ - public boolean isFastPort(short port_num); - - /** - * Return whether write throttling is enabled on the switch - */ - public boolean isWriteThrottleEnabled(); - - /** - * Set the flow table full flag in the switch - */ - public void setTableFull(boolean isFull); - - /** - * Set the suggested priority to use when installing access flows in - * this switch. - */ - public void setAccessFlowPriority(short prio); - - /** - * Set the suggested priority to use when installing core flows in - * this switch. - */ - public void setCoreFlowPriority(short prio); - - /** - * Get the suggested priority to use when installing access flows in - * this switch. - */ - public short getAccessFlowPriority(); - - /** - * Get the suggested priority to use when installing core flows in - * this switch. - */ - public short getCoreFlowPriority(); - - /** - * Start this switch driver's sub handshake. This might be a no-op but - * this method must be called at least once for the switch to be become - * ready. - * This method must only be called from the I/O thread - * @throws SwitchDriverSubHandshakeAlreadyStarted if the sub-handshake has - * already been started - */ - public void startDriverHandshake(); - - /** - * Check if the sub-handshake for this switch driver has been completed. - * This method can only be called after startDriverHandshake() - * - * This methods must only be called from the I/O thread - * @return true if the sub-handshake has been completed. False otherwise - * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has - * not been called yet. - */ - public boolean isDriverHandshakeComplete(); - - /** - * Pass the given OFMessage to the driver as part of this driver's - * sub-handshake. Must not be called after the handshake has been completed - * This methods must only be called from the I/O thread - * @param m The message that the driver should process - * @throws SwitchDriverSubHandshakeCompleted if isDriverHandshake() returns - * false before this method call - * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has - * not been called yet. - */ - public void processDriverHandshakeMessage(OFMessage m); -} diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java new file mode 100644 index 0000000000000000000000000000000000000000..58cc627860d679bb80975637604ca59314ec1daa --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java @@ -0,0 +1,189 @@ +/** +* Copyright 2011, Big Switch Networks, Inc. +* Originally created by David Erickson, Stanford University +* +* 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.core; + +import java.util.Collection; + +import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply; +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; +import org.projectfloodlight.openflow.protocol.OFPortStatus; + +import net.floodlightcontroller.util.OrderedCollection; + +/** + * An openflow switch connecting to the controller. This interface offers + * methods for interacting with switches using OpenFlow, and retrieving + * information about the switches. + */ +public interface IOFSwitchBackend extends IOFSwitch { + /** + * Set the netty Channel this switch instance is associated with + * Called immediately after instantiation + * @param channel + */ + void registerConnection(IOFConnectionBackend connection); + + /** + * Remove the netty Channels associated with this switch + * @param channel + */ + void removeConnections(); + + /** + * Remove the netty Channel belonging to the specified connection + * @param connection + */ + void removeConnection(IOFConnectionBackend connection); + + /** + * Set the OFFeaturesReply message returned by the switch during initial + * handshake. + * @param featuresReply + */ + void setFeaturesReply(OFFeaturesReply featuresReply); + + /** set the gentable mapping for this switch */ + void setGenTableMap(GenTableMap map); + + /** + * Add or modify a switch port. + * This is called by the core controller + * code in response to a OFPortStatus message. It should not typically be + * called by other floodlight applications. + * + * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow + * spec is not clear on whether portNames are portNumbers are considered + * authoritative identifiers. We treat portNames <-> portNumber mappings + * as fixed. If they change, we delete all previous conflicting ports and + * add all new ports. + * + * @param ps the port status message + * @return the ordered Collection of changes "applied" to the old ports + * of the switch according to the PortStatus message. A single PortStatus + * message can result in multiple changes. + * If portName <-> portNumber mappings have + * changed, the iteration order ensures that delete events for old + * conflicting appear before before events adding new ports + */ + OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps); + + /** + * Compute the changes that would be required to replace the old ports + * of this switch with the new ports + * @param ports new ports to set + * @return the ordered collection of changes "applied" to the old ports + * of the switch in order to set them to the new set. + * If portName <-> portNumber mappings have + * changed, the iteration order ensures that delete events for old + * conflicting appear before before events adding new ports + */ + OrderedCollection<PortChangeEvent> + comparePorts(Collection<OFPortDesc> ports); + + /** + * Replace the ports of this switch with the given ports. + * @param ports new ports to set + * @return the ordered collection of changes "applied" to the old ports + * of the switch in order to set them to the new set. + * If portName <-> portNumber mappings have + * changed, the iteration order ensures that delete events for old + * conflicting appear before before events adding new ports + */ + OrderedCollection<PortChangeEvent> + setPorts(Collection<OFPortDesc> ports); + + /*********************************************** + * The following method can be overridden by + * specific types of switches + *********************************************** + */ + + /** + * Set the SwitchProperties based on it's description + * @param description + */ + void setSwitchProperties(SwitchDescription description); + + /** + * Set the flow table full flag in the switch + */ + void setTableFull(boolean isFull); + + /** + * Start this switch driver's sub handshake. This might be a no-op but + * this method must be called at least once for the switch to be become + * ready. + * This method must only be called from the I/O thread + * @throws SwitchDriverSubHandshakeAlreadyStarted if the sub-handshake has + * already been started + */ + void startDriverHandshake(); + + /** + * Check if the sub-handshake for this switch driver has been completed. + * This method can only be called after startDriverHandshake() + * + * This methods must only be called from the I/O thread + * @return true if the sub-handshake has been completed. False otherwise + * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has + * not been called yet. + */ + boolean isDriverHandshakeComplete(); + + /** + * Pass the given OFMessage to the driver as part of this driver's + * sub-handshake. Must not be called after the handshake has been completed + * This methods must only be called from the I/O thread + * @param m The message that the driver should process + * @throws SwitchDriverSubHandshakeCompleted if isDriverHandshake() returns + * false before this method call + * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has + * not been called yet. + */ + void processDriverHandshakeMessage(OFMessage m); + + void setPortDescStats(OFPortDescStatsReply portDescStats); + + /** + * Cancel all pending request + */ + void cancelAllPendingRequests(); + + /** the the current HA role of this switch */ + void setControllerRole(OFControllerRole role); + + void setStatus(SwitchStatus switchStatus); + + /** + * Updates the switch's mapping of controller connections + * @param controllerCxnsReply the controller connections message sent from the switch + */ + void updateControllerConnections(OFBsnControllerConnectionsReply controllerCxnsReply); + + /** + * Determines whether there is another master controller that the switches are + * connected to by looking at the controller connections. + * @return true if another viable master exists + */ + boolean hasAnotherMaster(); + +} diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java index f7f720f914d34f6e812dc9032ccb135a8a3f100a..b56655535373e57b59e017791dce25834abe5649 100644 --- a/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java +++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java @@ -16,7 +16,10 @@ package net.floodlightcontroller.core; -import org.openflow.protocol.statistics.OFDescriptionStatistics; +import net.floodlightcontroller.core.IOFSwitchBackend; +import org.projectfloodlight.openflow.protocol.OFFactory; + +import net.floodlightcontroller.core.SwitchDescription; public interface IOFSwitchDriver { /** @@ -26,5 +29,5 @@ public interface IOFSwitchDriver { * @return A IOFSwitch instance if the driver found an implementation * for the given description. Null otherwise */ - public IOFSwitch getOFSwitchImpl(OFDescriptionStatistics description); -} + public IOFSwitchBackend getOFSwitchImpl(SwitchDescription description, OFFactory factory); +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java index e0c7b53f8b29eb8349f28d9f42cc97b43b309c8f..57eb4d179d27ad38d7202991ac26799bd822e6e7 100644 --- a/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java +++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java @@ -17,6 +17,9 @@ package net.floodlightcontroller.core; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.types.DatapathId; + /** * Switch lifecycle notifications. * @@ -45,20 +48,20 @@ public interface IOFSwitchListener { * the switch is connected at some controller in the cluster * @param switchId the datapath Id of the new switch */ - public void switchAdded(long switchId); + public void switchAdded(DatapathId switchId); /** * Fired when a switch disconnects from the cluster , * @param switchId the datapath Id of the switch */ - public void switchRemoved(long switchId); + public void switchRemoved(DatapathId switchId); /** * Fired when a switch becomes active *on the local controller*, I.e., * the switch is connected to the local controller and is in MASTER mode * @param switchId the datapath Id of the switch */ - public void switchActivated(long switchId); + public void switchActivated(DatapathId switchId); /** * Fired when a port on a known switch changes. @@ -74,9 +77,9 @@ public interface IOFSwitchListener { * @param port * @param type */ - public void switchPortChanged(long switchId, - ImmutablePort port, - IOFSwitch.PortChangeType type); + public void switchPortChanged(DatapathId switchId, + OFPortDesc port, + PortChangeType type); /** * Fired when any non-port related information (e.g., attributes, @@ -84,5 +87,5 @@ public interface IOFSwitchListener { * TODO: currently unused * @param switchId */ - public void switchChanged(long switchId); + public void switchChanged(DatapathId switchId); } diff --git a/src/main/java/net/floodlightcontroller/core/ImmutablePort.java b/src/main/java/net/floodlightcontroller/core/ImmutablePort.java deleted file mode 100644 index c015454cad15d3d24d85a0d0ddc89531062237d4..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/ImmutablePort.java +++ /dev/null @@ -1,561 +0,0 @@ -package net.floodlightcontroller.core; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; - -import net.floodlightcontroller.util.EnumBitmaps; -import org.openflow.protocol.OFPhysicalPort; -import org.openflow.protocol.OFPhysicalPort.OFPortConfig; -import org.openflow.protocol.OFPhysicalPort.OFPortFeatures; -import org.openflow.protocol.OFPhysicalPort.OFPortState; -import org.openflow.protocol.OFPhysicalPort.PortSpeed; -import org.openflow.util.HexString; - - -/** - * An immutable version of an OFPhysical port. In addition, it uses EnumSets - * instead of integer bitmaps to represent - * OFPortConfig, OFPortState, and OFPortFeature bitmaps. - * - * Port names are stored with the original case but equals() and XXXX use - * case-insentivie comparisions for port names!! - * - * TODO: create a Builder so we can easily construct OFPhysicalPorts - * TODO: should we verify / ensure that the features make sense, i.e., that - * currentFeatures IsSubsetOf advertisedFeatures IsSubsetOf - * supportedFeatures - * - * @author gregor - * - */ -public class ImmutablePort { - private final short portNumber; - private final byte[] hardwareAddress; - private final String name; - private final EnumSet<OFPortConfig> config; - private final boolean portStateLinkDown; - private final OFPortState stpState; - private final EnumSet<OFPortFeatures> currentFeatures; - private final EnumSet<OFPortFeatures> advertisedFeatures; - private final EnumSet<OFPortFeatures> supportedFeatures; - private final EnumSet<OFPortFeatures> peerFeatures; - - /** - * A builder class to create ImmutablePort instances - * - * TODO: add methods to remove elements from the EnumSets - */ - public static class Builder { - private short portNumber; - private byte[] hardwareAddress; - private String name; - private EnumSet<OFPortConfig> config; - private boolean portStateLinkDown; - private OFPortState stpState; - private EnumSet<OFPortFeatures> currentFeatures; - private EnumSet<OFPortFeatures> advertisedFeatures; - private EnumSet<OFPortFeatures> supportedFeatures; - private EnumSet<OFPortFeatures> peerFeatures; - - public Builder() { - this.portNumber = (short)1; - this.hardwareAddress = new byte[] { 0, 0, 0, 0, 0, 0 }; - this.name = ""; - this.config = EnumSet.noneOf(OFPortConfig.class); - this.portStateLinkDown = false; - this.stpState = OFPortState.OFPPS_STP_LISTEN; - this.currentFeatures = EnumSet.noneOf(OFPortFeatures.class); - this.advertisedFeatures = EnumSet.noneOf(OFPortFeatures.class); - this.supportedFeatures = EnumSet.noneOf(OFPortFeatures.class); - this.peerFeatures = EnumSet.noneOf(OFPortFeatures.class); - } - - public Builder(ImmutablePort p) { - this.portNumber = p.getPortNumber(); - this.hardwareAddress = p.getHardwareAddress(); - this.name = p.getName(); - this.config = EnumSet.copyOf(p.getConfig()); - this.portStateLinkDown = p.isLinkDown(); - this.stpState = p.getStpState(); - this.currentFeatures = EnumSet.copyOf(p.getCurrentFeatures()); - this.advertisedFeatures = EnumSet.copyOf(p.getAdvertisedFeatures()); - this.supportedFeatures = EnumSet.copyOf(p.getSupportedFeatures()); - this.peerFeatures = EnumSet.copyOf(p.getPeerFeatures()); - } - - /** - * @param portNumber the portNumber to set - */ - public Builder setPortNumber(short portNumber) { - this.portNumber = portNumber; - return this; - } - /** - * @param hardwareAddress the hardwareAddress to set - */ - public Builder setHardwareAddress(byte[] hardwareAddress) { - if (hardwareAddress== null) { - throw new NullPointerException("Hardware address must not be null"); - } - if (hardwareAddress.length != 6) { - throw new IllegalArgumentException("Harware address must be 6 " + - "bytes long but hardware address is " + - Arrays.toString(hardwareAddress)); - } - this.hardwareAddress = Arrays.copyOf(hardwareAddress, 6); - return this; - } - /** - * @param name the name to set - */ - public Builder setName(String name) { - if (name == null) - throw new NullPointerException("Port name must not be null"); - this.name = name; - return this; - } - /** - * @param config the config to set - */ - public Builder addConfig(OFPortConfig config) { - if (config == null) - throw new NullPointerException("PortConfig must not be null"); - this.config.add(config); - return this; - } - /** - * @param portStateLinkDown the portStateLinkDown to set - */ - public Builder setPortStateLinkDown(boolean portStateLinkDown) { - this.portStateLinkDown = portStateLinkDown; - return this; - } - /** - * @param stpState the stpState to set - */ - public Builder setStpState(OFPortState stpState) { - if (stpState == null) - throw new NullPointerException("stpState must not be null"); - if (!stpState.isStpState()) { - String msg = String.format("OFPortState enum constant %s " + - "is not an STP state", stpState); - throw new IllegalArgumentException(msg); - } - this.stpState = stpState; - return this; - } - /** - * @param currentFeatures the currentFeatures to set - */ - public Builder addCurrentFeature(OFPortFeatures currentFeature) { - if (currentFeature == null) - throw new NullPointerException("CurrentFeature must not be null"); - this.currentFeatures.add(currentFeature); - return this; - } - /** - * @param advertisedFeatures the advertisedFeatures to set - */ - public Builder - addAdvertisedFeature(OFPortFeatures advertisedFeature) { - if (advertisedFeature == null) { - throw new - NullPointerException("AdvertisedFeature must not be null"); - } - this.advertisedFeatures.add(advertisedFeature); - return this; - } - /** - * @param supportedFeatures the supportedFeatures to set - */ - public Builder addSupportedFeature(OFPortFeatures supportedFeature) { - if (supportedFeature == null) { - throw new NullPointerException("SupportedFeature must not be null"); - } - this.supportedFeatures.add(supportedFeature); - return this; - } - /** - * @param peerFeatures the peerFeatures to set - */ - public Builder addPeerFeature(OFPortFeatures peerFeature) { - if (peerFeature == null) - throw new NullPointerException("PortFeature must not be null"); - this.peerFeatures.add(peerFeature); - return this; - } - - /** - * @return - */ - public ImmutablePort build() { - return new ImmutablePort(portNumber, - hardwareAddress, - name, - EnumSet.copyOf(config), - portStateLinkDown, - stpState, - EnumSet.copyOf(currentFeatures), - EnumSet.copyOf(advertisedFeatures), - EnumSet.copyOf(supportedFeatures), - EnumSet.copyOf(peerFeatures)); - } - } - - - public static ImmutablePort fromOFPhysicalPort(OFPhysicalPort p) { - if (p == null) { - throw new NullPointerException("OFPhysicalPort must not be null"); - } - if (p.getHardwareAddress() == null) { - throw new NullPointerException("Hardware address must not be null"); - } - if (p.getName() == null) { - throw new NullPointerException("Port name must not be null"); - } - - return new ImmutablePort( - - p.getPortNumber(), - Arrays.copyOf(p.getHardwareAddress(), 6), - p.getName(), - EnumBitmaps.toEnumSet(OFPortConfig.class, p.getConfig()), - OFPortState.isPortDown(p.getState()), - OFPortState.getStpState(p.getState()), - EnumBitmaps.toEnumSet(OFPortFeatures.class, - p.getCurrentFeatures()), - EnumBitmaps.toEnumSet(OFPortFeatures.class, - p.getAdvertisedFeatures()), - EnumBitmaps.toEnumSet(OFPortFeatures.class, - p.getSupportedFeatures()), - EnumBitmaps.toEnumSet(OFPortFeatures.class, - p.getPeerFeatures()) - ); - } - - public static ImmutablePort create(String name, Short portNumber) { - return new ImmutablePort(portNumber, - new byte[] { 0, 0, 0, 0, 0, 0 }, - name, - EnumSet.noneOf(OFPortConfig.class), - false, - OFPortState.OFPPS_STP_LISTEN, - EnumSet.noneOf(OFPortFeatures.class), - EnumSet.noneOf(OFPortFeatures.class), - EnumSet.noneOf(OFPortFeatures.class), - EnumSet.noneOf(OFPortFeatures.class)); - } - - /** - * Private constructor. Use factory methods. - * - * Verifies pre-conditions of arguments - * Does NOT make defensive copies. Calling factory methods are required - * to copy defensively if required. - * - * @param portNumber - * @param hardwareAddress - * @param name - * @param config - * @param portStateLinkDown - * @param portStateStp - * @param currentFeatures - * @param advertisedFeatures - * @param supportedFeatures - * @param peerFeatures - */ - private ImmutablePort(short portNumber, byte[] hardwareAddress, - String name, EnumSet<OFPortConfig> config, - boolean portStateLinkDown, - OFPortState portStateStp, - EnumSet<OFPortFeatures> currentFeatures, - EnumSet<OFPortFeatures> advertisedFeatures, - EnumSet<OFPortFeatures> supportedFeatures, - EnumSet<OFPortFeatures> peerFeatures) { - if (name == null) { - throw new NullPointerException("Port name must not be null"); - } - if (hardwareAddress== null) { - throw new NullPointerException("Hardware address must not be null"); - } - if (hardwareAddress.length != 6) { - throw new IllegalArgumentException("Harware address must be 6 " + - "bytes long but hardware address is " + - Arrays.toString(hardwareAddress)); - } - if (config == null) - throw new NullPointerException("portConfig must not be null"); - if (portStateStp == null) - throw new NullPointerException("portStateStp must not be null"); - if (currentFeatures == null) - throw new NullPointerException("currentFeatures must not be null"); - if (advertisedFeatures == null) - throw new NullPointerException("advertisedFeatures must not be null"); - if (supportedFeatures == null) - throw new NullPointerException("supportedFeatures must not be null"); - if (peerFeatures == null) - throw new NullPointerException("peerFeatures must not be null"); - - this.portNumber = portNumber; - this.hardwareAddress = hardwareAddress; - this.name = name; - this.config = config; - this.portStateLinkDown = portStateLinkDown; - this.stpState = portStateStp; - this.currentFeatures = currentFeatures; - this.advertisedFeatures = advertisedFeatures; - this.supportedFeatures = supportedFeatures; - this.peerFeatures = peerFeatures; - } - - public short getPortNumber() { - return portNumber; - } - - public byte[] getHardwareAddress() { - // FIXME: don't use arrays. - return Arrays.copyOf(hardwareAddress, 6); - } - - public String getName() { - return name; - } - - public Set<OFPortConfig> getConfig() { - return Collections.unmodifiableSet(config); - } - - /** - * Returns true if the OFPortState indicates the port is down - * @return - */ - public boolean isLinkDown() { - return portStateLinkDown; - } - - /** - * Returns the STP state portion of the OFPortState. The returned - * enum constant will be one of the four STP states and will have - * isStpState() return true - * @return - */ - public OFPortState getStpState() { - return this.stpState; - } - - public Set<OFPortFeatures> getCurrentFeatures() { - return Collections.unmodifiableSet(currentFeatures); - } - - public Set<OFPortFeatures> getAdvertisedFeatures() { - return Collections.unmodifiableSet(advertisedFeatures); - } - - public Set<OFPortFeatures> getSupportedFeatures() { - return Collections.unmodifiableSet(supportedFeatures); - } - - public Set<OFPortFeatures> getPeerFeatures() { - return Collections.unmodifiableSet(peerFeatures); - } - - - /** - * Returns true if the port is up, i.e., it's neither administratively - * down nor link down. It currently does NOT take STP state into - * consideration - * @return - */ - public boolean isEnabled() { - return (!portStateLinkDown && - !config.contains(OFPortConfig.OFPPC_PORT_DOWN)); - } - - /** - * @return the speed of the port (from currentFeatures) if the port is - * enabled, otherwise return SPEED_NONE - */ - public PortSpeed getCurrentPortSpeed() { - if (!isEnabled()) - return PortSpeed.SPEED_NONE; - PortSpeed maxSpeed = PortSpeed.SPEED_NONE; - for (OFPortFeatures f: currentFeatures) - PortSpeed.max(maxSpeed, f.getSpeed()); - return maxSpeed; - } - - public OFPhysicalPort toOFPhysicalPort() { - OFPhysicalPort ofpp = new OFPhysicalPort(); - ofpp.setPortNumber(this.getPortNumber()); - ofpp.setHardwareAddress(this.getHardwareAddress()); - ofpp.setName(this.getName()); - ofpp.setConfig(EnumBitmaps.toBitmap(this.getConfig())); - int state = this.getStpState().getValue(); - if (this.isLinkDown()) - state |= OFPortState.OFPPS_LINK_DOWN.getValue(); - ofpp.setState(state); - ofpp.setCurrentFeatures(EnumBitmaps.toBitmap(this.getCurrentFeatures())); - ofpp.setAdvertisedFeatures( - EnumBitmaps.toBitmap(this.getAdvertisedFeatures())); - ofpp.setSupportedFeatures( - EnumBitmaps.toBitmap(this.getSupportedFeatures())); - ofpp.setPeerFeatures(EnumBitmaps.toBitmap(this.getPeerFeatures())); - return ofpp; - } - - /** - * Return a brief String describing this port containing the port number - * and port name - * @return - */ - public String toBriefString() { - return String.format("%s (%d)", name, portNumber); - } - - - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime - * result - + ((advertisedFeatures == null) ? 0 - : advertisedFeatures.hashCode()); - result = prime * result + ((config == null) ? 0 : config.hashCode()); - result = prime - * result - + ((currentFeatures == null) ? 0 - : currentFeatures.hashCode()); - result = prime * result + Arrays.hashCode(hardwareAddress); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result - + ((peerFeatures == null) ? 0 : peerFeatures.hashCode()); - result = prime * result + portNumber; - result = prime * result + (portStateLinkDown ? 1231 : 1237); - result = prime * result - + ((stpState == null) ? 0 : stpState.hashCode()); - result = prime - * result - + ((supportedFeatures == null) ? 0 - : supportedFeatures.hashCode()); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - ImmutablePort other = (ImmutablePort) obj; - if (portNumber != other.portNumber) return false; - if (name == null) { - if (other.name != null) return false; - } else if (!name.equalsIgnoreCase(other.name)) return false; - if (advertisedFeatures == null) { - if (other.advertisedFeatures != null) return false; - } else if (!advertisedFeatures.equals(other.advertisedFeatures)) - return false; - if (config == null) { - if (other.config != null) return false; - } else if (!config.equals(other.config)) return false; - if (currentFeatures == null) { - if (other.currentFeatures != null) return false; - } else if (!currentFeatures.equals(other.currentFeatures)) - return false; - if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) - return false; - if (peerFeatures == null) { - if (other.peerFeatures != null) return false; - } else if (!peerFeatures.equals(other.peerFeatures)) return false; - if (portStateLinkDown != other.portStateLinkDown) return false; - if (stpState != other.stpState) return false; - if (supportedFeatures == null) { - if (other.supportedFeatures != null) return false; - } else if (!supportedFeatures.equals(other.supportedFeatures)) - return false; - return true; - } - - /** - * Convert a Collection of OFPhysicalPorts to a list of ImmutablePorts. - * All OFPhysicalPorts in the Collection must be non-null and valid. - * No other checks (name / number uniqueness) are performed - * @param ports - * @return a list of {@link ImmutablePort}s. This is list is owned by - * the caller. The returned list is not thread-safe - * @throws NullPointerException if any OFPhysicalPort or important fields - * of any OFPhysicalPort are null - * @throws IllegalArgumentException - */ - public static List<ImmutablePort> - immutablePortListOf(Collection<OFPhysicalPort> ports) { - if (ports == null) { - throw new NullPointerException("Port list must not be null"); - } - ArrayList<ImmutablePort> immutablePorts = - new ArrayList<ImmutablePort>(ports.size()); - for (OFPhysicalPort p: ports) - immutablePorts.add(fromOFPhysicalPort(p)); - return immutablePorts; - } - - /** - * Convert a Collection of ImmutablePort to a list of OFPhyscialPorts. - * All ImmutablePorts in the Collection must be non-null. - * No other checks (name / number uniqueness) are performed - * @param ports - * @return a list of {@link OFPhysicalPort}s. This is list is owned by - * the caller. The returned list is not thread-safe - * @throws NullPointerException if any {@link ImmutablePort} or the port - * list is null - * @throws IllegalArgumentException - */ - public static List<OFPhysicalPort> - ofPhysicalPortListOf(Collection<ImmutablePort> ports) { - if (ports == null) { - throw new NullPointerException("Port list must not be null"); - } - ArrayList<OFPhysicalPort> ofppList= - new ArrayList<OFPhysicalPort>(ports.size()); - for (ImmutablePort p: ports) { - if (p == null) - throw new NullPointerException("Port must not be null"); - ofppList.add(p.toOFPhysicalPort()); - } - return ofppList; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - StringBuilder builder2 = new StringBuilder(); - String linkState = (portStateLinkDown) ? "DOWN" : "UP"; - builder2.append("Port [") - .append(name) - .append("(").append(portNumber).append(")") - .append(", hardwareAddress=") - .append(HexString.toHexString(hardwareAddress)) - .append(", config=").append(config) - .append(", link=").append(linkState) - .append(", stpState=").append(stpState) - .append(", currentFeatures=").append(currentFeatures) - .append(", advertisedFeatures=").append(advertisedFeatures) - .append(", supportedFeatures=").append(supportedFeatures) - .append(", peerFeatures=").append(peerFeatures).append("]"); - return builder2.toString(); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java b/src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java new file mode 100644 index 0000000000000000000000000000000000000000..514d3541cbfc06820205ad40e9f3499bf441ceba --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java @@ -0,0 +1,68 @@ +package net.floodlightcontroller.core; + +import javax.annotation.Nonnull; + +import org.projectfloodlight.openflow.types.OFAuxId; + +/** + * Immutable class for logical OF message category. + * Applications should use these to define the OF Aux connections + * that they desire. + * @author Jason Parraga <Jason.Parraga@bigswitch.com> + */ +public class LogicalOFMessageCategory { + + public static final LogicalOFMessageCategory MAIN = new LogicalOFMessageCategory("MAIN", OFAuxId.MAIN); + + final private String name; + final private OFAuxId auxId; + + + public LogicalOFMessageCategory(@Nonnull String name, int auxId) { + this(name, OFAuxId.of(auxId)); + } + + public LogicalOFMessageCategory(@Nonnull String name, OFAuxId auxId) { + if (name == null) + throw new NullPointerException("name must not be null"); + this.name = name; + this.auxId = auxId; + } + + public OFAuxId getAuxId(){ + return this.auxId; + } + + public String getName(){ + return this.name; + } + + @Override + public String toString(){ + return "LogicalOFMessageCategory [name=" + getName() + " OFAuxId=" + getAuxId() + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((auxId == null) ? 0 : auxId.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + LogicalOFMessageCategory other = (LogicalOFMessageCategory) obj; + if (auxId == null) { + if (other.auxId != null) return false; + } else if (!auxId.equals(other.auxId)) return false; + if (name == null) { + if (other.name != null) return false; + } else if (!name.equals(other.name)) return false; + return true; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/Main.java b/src/main/java/net/floodlightcontroller/core/Main.java index 627a56c1477f2191abc11f2f8dbc5304128c0bd6..f57ed991a385aebd94dcb4a9d2e68f2e95dfa9f7 100644 --- a/src/main/java/net/floodlightcontroller/core/Main.java +++ b/src/main/java/net/floodlightcontroller/core/Main.java @@ -18,48 +18,68 @@ package net.floodlightcontroller.core; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.floodlightcontroller.core.internal.CmdLineSettings; +import net.floodlightcontroller.core.module.FloodlightModuleConfigFileNotFoundException; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.FloodlightModuleLoader; import net.floodlightcontroller.core.module.IFloodlightModuleContext; -import net.floodlightcontroller.restserver.IRestApiService; /** * Host for the Floodlight main method * @author alexreimers */ public class Main { + private static final Logger logger = LoggerFactory.getLogger(Main.class); - /** - * Main method to load configuration and modules - * @param args - * @throws FloodlightModuleException - */ - public static void main(String[] args) throws FloodlightModuleException { - // Setup logger - System.setProperty("org.restlet.engine.loggerFacadeClass", - "org.restlet.ext.slf4j.Slf4jLoggerFacade"); - - CmdLineSettings settings = new CmdLineSettings(); - CmdLineParser parser = new CmdLineParser(settings); - try { - parser.parseArgument(args); - } catch (CmdLineException e) { - parser.printUsage(System.out); - System.exit(1); - } - - // Load modules - FloodlightModuleLoader fml = new FloodlightModuleLoader(); - IFloodlightModuleContext moduleContext = fml.loadModulesFromConfig(settings.getModuleFile()); - // Run REST server - IRestApiService restApi = moduleContext.getServiceImpl(IRestApiService.class); - restApi.run(); - // Run the main floodlight module - IFloodlightProviderService controller = - moduleContext.getServiceImpl(IFloodlightProviderService.class); - // This call blocks, it has to be the last line in the main - controller.run(); - } + /** + * Main method to load configuration and modules + * @param args + * @throws FloodlightModuleException + */ + public static void main(String[] args) throws FloodlightModuleException { + try { + // Setup logger + System.setProperty("org.restlet.engine.loggerFacadeClass", + "org.restlet.ext.slf4j.Slf4jLoggerFacade"); + + CmdLineSettings settings = new CmdLineSettings(); + CmdLineParser parser = new CmdLineParser(settings); + try { + parser.parseArgument(args); + } catch (CmdLineException e) { + parser.printUsage(System.out); + System.exit(1); + } + + // Load modules + FloodlightModuleLoader fml = new FloodlightModuleLoader(); + try { + IFloodlightModuleContext moduleContext = fml.loadModulesFromConfig(settings.getModuleFile()); + //TODO @Ryan I don't think we need this anymore... Run REST server + //IRestApiService restApi = moduleContext.getServiceImpl(IRestApiService.class); + //restApi.run(); + // Run the main floodlight module + //IFloodlightProviderService controller = + // moduleContext.getServiceImpl(IFloodlightProviderService.class); + // This call blocks, it has to be the last line in the main + //controller.run(); + } catch (FloodlightModuleConfigFileNotFoundException e) { + // we really want to log the message, not the stack trace + logger.error("Could not read config file: {}", e.getMessage()); + System.exit(1); + } + try { + fml.runModules(); // this should run the controller module and all modules + } catch (FloodlightModuleException e) { + logger.error("Failed to run controller modules", e); + System.exit(1); + } + } catch (Exception e) { + logger.error("Exception in main", e); + System.exit(1); + } + } } diff --git a/src/main/java/net/floodlightcontroller/core/OFConnection.java b/src/main/java/net/floodlightcontroller/core/OFConnection.java new file mode 100644 index 0000000000000000000000000000000000000000..ff4f529bf92c0e372967cdc5dd66fd507f34af53 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/OFConnection.java @@ -0,0 +1,409 @@ +/** + * Copyright 2012, Big Switch Networks, Inc. + * Originally created by David Erickson, Stanford University + * + * 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.core; + +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.annotation.Nonnull; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.util.Timeout; +import org.jboss.netty.util.Timer; +import org.jboss.netty.util.TimerTask; + +import java.util.Date; + +import net.floodlightcontroller.core.annotations.LogMessageDoc; +import net.floodlightcontroller.core.internal.Controller; +import net.floodlightcontroller.core.internal.IOFConnectionListener; +import net.floodlightcontroller.debugcounter.IDebugCounterService; + +import org.projectfloodlight.openflow.protocol.OFErrorMsg; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFRequest; +import org.projectfloodlight.openflow.protocol.OFStatsReply; +import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; +import org.projectfloodlight.openflow.protocol.OFStatsRequest; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFAuxId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Implementation of an openflow connection to switch. Encapsulates a + * {@link Channel}, and provides message write and request/response handling + * capabilities. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class OFConnection implements IOFConnection, IOFConnectionBackend{ + private static final Logger logger = LoggerFactory.getLogger(OFConnection.class); + private final DatapathId dpid; + private final OFFactory factory; + private final Channel channel; + private final OFAuxId auxId; + private final Timer timer; + + private final Date connectedSince; + + private final Map<Long, Deliverable<?>> xidDeliverableMap; + + protected final static ThreadLocal<List<OFMessage>> localMsgBuffer = + new ThreadLocal<List<OFMessage>>(); + + private static final long DELIVERABLE_TIME_OUT = 60; + private static final TimeUnit DELIVERABLE_TIME_OUT_UNIT = TimeUnit.SECONDS; + + + private final OFConnectionCounters counters; + private IOFConnectionListener listener; + + public OFConnection(@Nonnull DatapathId dpid, + @Nonnull OFFactory factory, + @Nonnull Channel channel, + @Nonnull OFAuxId auxId, + @Nonnull IDebugCounterService debugCounters, + @Nonnull Timer timer) { + Preconditions.checkNotNull(dpid, "dpid"); + Preconditions.checkNotNull(factory, "factory"); + Preconditions.checkNotNull(channel, "channel"); + Preconditions.checkNotNull(timer, "timer"); + Preconditions.checkNotNull(debugCounters); + + this.listener = NullConnectionListener.INSTANCE; + this.dpid = dpid; + this.factory = factory; + this.channel = channel; + this.auxId = auxId; + this.connectedSince = new Date(); + this.xidDeliverableMap = new ConcurrentHashMap<>(); + this.counters = new OFConnectionCounters(debugCounters, dpid, this.auxId); + this.timer = timer; + } + + @Override + public void write(OFMessage m) { + if (!isConnected()) { + if (logger.isDebugEnabled()) + logger.debug("{}: not connected - dropping message {}", this, m); + return; + } + if (logger.isTraceEnabled()) + logger.trace("{}: send {}", this, m); + List<OFMessage> msgBuffer = localMsgBuffer.get(); + if (msgBuffer == null) { + msgBuffer = new ArrayList<OFMessage>(); + localMsgBuffer.set(msgBuffer); + } + + counters.updateWriteStats(m); + msgBuffer.add(m); + + if ((msgBuffer.size() >= Controller.BATCH_MAX_SIZE) + || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) { + this.write(msgBuffer); + localMsgBuffer.set(null); + } + } + + @Override + public <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request) { + if (!isConnected()) + return Futures.immediateFailedFuture(new SwitchDisconnectedException(getDatapathId())); + + DeliverableListenableFuture<R> future = new DeliverableListenableFuture<R>(); + xidDeliverableMap.put(request.getXid(), future); + write(request); + return future; + } + + @Override + @LogMessageDoc(level = "WARN", + message = "Sending OF message that modifies switch " + + "state while in the slave role: {switch}", + explanation = "An application has sent a message to a switch " + + "that is not valid when the switch is in a slave role", + recommendation = LogMessageDoc.REPORT_CONTROLLER_BUG) + public void write(Iterable<OFMessage> msglist) { + if (!isConnected()) { + if (logger.isDebugEnabled()) + logger.debug(this.toString() + " : not connected - dropping {} element msglist {} ", + Iterables.size(msglist), + String.valueOf(msglist).substring(0, 80)); + return; + } + for (OFMessage m : msglist) { + if (logger.isTraceEnabled()) + logger.trace("{}: send {}", this, m); + counters.updateWriteStats(m); + } + this.channel.write(msglist); + } + + // Notifies the connection object that the channel has been disconnected + public void disconnected() { + SwitchDisconnectedException exception = new SwitchDisconnectedException(getDatapathId()); + for (Long xid : xidDeliverableMap.keySet()) { + // protect against other mechanisms running at the same time + // (timeout) + Deliverable<?> removed = xidDeliverableMap.remove(xid); + if (removed != null) { + removed.deliverError(exception); + } + } + } + + @Override + public void disconnect() { + this.channel.disconnect(); + } + + @Override + public String toString() { + String channelString = (channel != null) ? String.valueOf(channel.getRemoteAddress()): "?"; + return "OFConnection [" + getDatapathId() + "(" + getAuxId() + ")" + "@" + channelString + "]"; + } + + @Override + public Date getConnectedSince() { + return connectedSince; + } + + @Override + public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest( + OFStatsRequest<REPLY> request) { + if (!isConnected()) + return Futures.immediateFailedFuture(new SwitchDisconnectedException(getDatapathId())); + + final DeliverableListenableFuture<List<REPLY>> future = + new DeliverableListenableFuture<List<REPLY>>(); + + Deliverable<REPLY> deliverable = new Deliverable<REPLY>() { + private final List<REPLY> results = Collections + .synchronizedList(new ArrayList<REPLY>()); + + @Override + public void deliver(REPLY reply) { + results.add(reply); + if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { + // done + future.deliver(results); + } + } + + @Override + public void deliverError(Throwable cause) { + future.deliverError(cause); + } + + @Override + public boolean isDone() { + return future.isDone(); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return future.cancel(mayInterruptIfRunning); + } + }; + + registerDeliverable(request.getXid(), deliverable); + this.write(request); + return future; + } + + private void registerDeliverable(long xid, Deliverable<?> deliverable) { + this.xidDeliverableMap.put(xid, deliverable); + timer.newTimeout(new TimeOutDeliverable(xid), DELIVERABLE_TIME_OUT, DELIVERABLE_TIME_OUT_UNIT); + } + + public boolean handleGenericDeliverable(OFMessage reply) { + counters.updateReadStats(reply); + @SuppressWarnings("unchecked") + Deliverable<OFMessage> deliverable = + (Deliverable<OFMessage>) this.xidDeliverableMap.get(reply.getXid()); + if (deliverable != null) { + if(reply instanceof OFErrorMsg) { + deliverable.deliverError(new OFErrorMsgException((OFErrorMsg) reply)); + } else { + deliverable.deliver(reply); + } + if (deliverable.isDone()) + this.xidDeliverableMap.remove(reply.getXid()); + return true; + } else { + return false; + } + } + + @Override + public void cancelAllPendingRequests() { + /* + * we don't need to be synchronized here. Even if another thread + * modifies the map while we're cleaning up the future will eventually + * timeout + */ + for (Deliverable<?> d : xidDeliverableMap.values()) { + d.cancel(true); + } + xidDeliverableMap.clear(); + } + + @Override + public boolean isConnected() { + return channel.isConnected(); + } + + @Override + public void flush() { + List<OFMessage> msglist = localMsgBuffer.get(); + if ((msglist != null) && (msglist.size() > 0)) { + this.write(msglist); + localMsgBuffer.set(null); + } + } + + @Override + public SocketAddress getRemoteInetAddress() { + return channel.getRemoteAddress(); + } + + @Override + public SocketAddress getLocalInetAddress() { + return channel.getLocalAddress(); + } + + public boolean deliverResponse(OFMessage m) { + if (handleGenericDeliverable(m)) + return true; + else + return false; + } + + @Override + public boolean isWritable() { + return channel.isWritable(); + } + + @Override + public DatapathId getDatapathId() { + return dpid; + } + + @Override + public OFAuxId getAuxId() { + return auxId; + } + + Set<Long> getPendingRequestIds() { + return ImmutableSet.copyOf(xidDeliverableMap.keySet()); + } + + @Override + public OFFactory getOFFactory() { + return this.factory; + } + + /** + * Timeout class instantiated for deliverables. Will throw a timeout exception + * if proper responses are not received in time. + * + */ + private class TimeOutDeliverable implements TimerTask { + private final long xid; + + public TimeOutDeliverable(long xid) { + this.xid = xid; + } + + @Override + public void run(Timeout timeout) throws Exception { + Deliverable<?> removed = xidDeliverableMap.remove(xid); + if (removed != null && !removed.isDone()) { + removed.deliverError(new TimeoutException( + "timeout - did not receive answer for xid " + xid)); + } + + } + } + + public IOFConnectionListener getListener() { + return listener; + } + + /** set the connection listener + * <p> + * Note: this is assumed to be called from the Connection's IO Thread. + * + * @param listener + */ + @Override + public void setListener(IOFConnectionListener listener) { + this.listener = listener; + } + + public void messageReceived(OFMessage m) { + // Check if message was a response for a xid waiting at the switch + if(!deliverResponse(m)){ + listener.messageReceived(this, m); + } + } + + /** A dummy connection listener that just logs warn messages. Saves us a few null checks + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ + private static class NullConnectionListener implements IOFConnectionListener { + public final static NullConnectionListener INSTANCE = new NullConnectionListener(); + + private NullConnectionListener() { } + + @Override + public void connectionClosed(IOFConnectionBackend connection) { + logger.warn("NullConnectionListener for {} - received connectionClosed", connection); + } + + @Override + public void messageReceived(IOFConnectionBackend connection, OFMessage m) { + logger.warn("NullConnectionListener for {} - received messageReceived: {}", connection, m); + } + + @Override + public boolean isSwitchHandshakeComplete(IOFConnectionBackend connection) { + return false; + } + + } + + +} diff --git a/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java b/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java new file mode 100644 index 0000000000000000000000000000000000000000..403fb4bbda1c3bd0ec87c8423df624e45b69ab96 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java @@ -0,0 +1,710 @@ +package net.floodlightcontroller.core; + +import net.floodlightcontroller.debugcounter.IDebugCounter; +import net.floodlightcontroller.debugcounter.IDebugCounterService; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFAuxId; +import org.python.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Implementation of Counters for per-connection statistics for OpenFlow + * messages. + * @author Alok Shankar <alok@bigswitch.com> + */ +public class OFConnectionCounters { + public static final String COUNTER_MODULE = OFConnectionCounters.class.getPackage().getName(); + + /** + * Counters for open flow message types + */ + // Write Counters + // + private final IDebugCounter ctrWriteHello; + private final IDebugCounter ctrWriteError; + private final IDebugCounter ctrWriteEchoRequest; + private final IDebugCounter ctrWriteEchoReply; + private final IDebugCounter ctrWriteExperimenter; + private final IDebugCounter ctrWriteFeaturesRequest; + private final IDebugCounter ctrWriteFeaturesReply; + private final IDebugCounter ctrWriteGetConfigRequest; + private final IDebugCounter ctrWriteGetConfigReply; + private final IDebugCounter ctrWriteSetConfig; + private final IDebugCounter ctrWritePacketIn; + private final IDebugCounter ctrWritePacketOut; + private final IDebugCounter ctrWriteFlowRemoved; + private final IDebugCounter ctrWritePortStatus; + private final IDebugCounter ctrWriteFlowMod; + private final IDebugCounter ctrWritePortMod; + private final IDebugCounter ctrWriteStatsRequest; + private final IDebugCounter ctrWriteStatsReply; + private final IDebugCounter ctrWriteBarrierRequest; + private final IDebugCounter ctrWriteBarrierReply; + private final IDebugCounter ctrWriteGetAsyncReply; + private final IDebugCounter ctrWriteGetAsyncRequest; + private final IDebugCounter ctrWriteGroupMod; + private final IDebugCounter ctrWriteMeterMod; + private final IDebugCounter ctrWriteQueueGetConfigReply; + private final IDebugCounter ctrWriteQueueGetConfigRequest; + private final IDebugCounter ctrWriteRoleRequest; + private final IDebugCounter ctrWriteRoleReply; + private final IDebugCounter ctrWriteSetAsync; + private final IDebugCounter ctrWriteTableMod; + + // Read Counters + // + private final IDebugCounter ctrReadHello; + private final IDebugCounter ctrReadError; + private final IDebugCounter ctrReadEchoRequest; + private final IDebugCounter ctrReadEchoReply; + private final IDebugCounter ctrReadExperimenter; + private final IDebugCounter ctrReadFeaturesRequest; + private final IDebugCounter ctrReadFeaturesReply; + private final IDebugCounter ctrReadGetConfigRequest; + private final IDebugCounter ctrReadGetConfigReply; + private final IDebugCounter ctrReadSetConfig; + private final IDebugCounter ctrReadPacketIn; + private final IDebugCounter ctrReadPacketOut; + private final IDebugCounter ctrReadFlowRemoved; + private final IDebugCounter ctrReadPortStatus; + private final IDebugCounter ctrReadFlowMod; + private final IDebugCounter ctrReadPortMod; + private final IDebugCounter ctrReadStatsRequest; + private final IDebugCounter ctrReadStatsReply; + private final IDebugCounter ctrReadBarrierRequest; + private final IDebugCounter ctrReadBarrierReply; + private final IDebugCounter ctrReadGetAsyncReply; + private final IDebugCounter ctrReadGetAsyncRequest; + private final IDebugCounter ctrReadGroupMod; + private final IDebugCounter ctrReadMeterMod; + private final IDebugCounter ctrReadQueueGetConfigReply; + private final IDebugCounter ctrReadQueueGetConfigRequest; + private final IDebugCounter ctrReadRoleRequest; + private final IDebugCounter ctrReadRoleReply; + private final IDebugCounter ctrReadSetAsync; + private final IDebugCounter ctrReadTableMod; + + private static final Logger logger = + LoggerFactory.getLogger(OFConnectionCounters.class); + + /** + * Utility function to create description string and do counter registration + * @param countersService + * @param stringId The string ID + * @param messageType Type of open flow message + * @return the registered DebugCounter + */ + IDebugCounter registerCounterLocal(IDebugCounterService countersService, + String hierarchy, + String stringId, + String messageType){ + String counterHierarchy = stringId + hierarchy + "/" + messageType; + String counterDescription = "Number of " + messageType + + " messages in this connection"; + + return countersService.registerCounter(COUNTER_MODULE, counterHierarchy, + counterDescription); + } + + public OFConnectionCounters(IDebugCounterService counters, + DatapathId dpid, + OFAuxId auxId) { + + Preconditions.checkNotNull(counters, "Counters must not be null"); + Preconditions.checkNotNull(dpid, "dpid must not be null"); + Preconditions.checkNotNull(auxId, "auxid must not be null"); + + String stringId = dpid.toString() +":" + auxId.toString(); + String hierarchy = "/write"; + + // every level of the hierarchical counter has to be registered + // even if they are not used + + counters.registerCounter(COUNTER_MODULE, stringId , + "Counter for this connection"); + + registerCounterLocal(counters, + hierarchy, + stringId, + ""); + + ctrWriteHello = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.HELLO.toString()); + ctrWriteError = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ERROR.toString()); + ctrWriteEchoRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ECHO_REQUEST.toString()); + ctrWriteEchoReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ECHO_REPLY.toString()); + ctrWriteExperimenter = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.EXPERIMENTER.toString()); + ctrWriteFeaturesRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FEATURES_REQUEST.toString()); + ctrWriteFeaturesReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FEATURES_REPLY.toString()); + ctrWriteGetConfigRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_CONFIG_REQUEST.toString()); + ctrWriteGetConfigReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_CONFIG_REPLY.toString()); + ctrWriteSetConfig = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.SET_CONFIG.toString()); + ctrWritePacketIn = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PACKET_IN.toString()); + ctrWritePacketOut = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PACKET_OUT.toString()); + ctrWriteFlowRemoved = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FLOW_REMOVED.toString()); + ctrWritePortStatus = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PORT_STATUS.toString()); + ctrWriteFlowMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FLOW_MOD.toString()); + ctrWritePortMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PORT_MOD.toString()); + ctrWriteStatsRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.STATS_REQUEST.toString()); + ctrWriteStatsReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.STATS_REPLY.toString()); + ctrWriteBarrierRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.BARRIER_REQUEST.toString()); + ctrWriteBarrierReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.BARRIER_REPLY.toString()); + ctrWriteGetAsyncReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_ASYNC_REPLY.toString()); + ctrWriteGetAsyncRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_ASYNC_REQUEST.toString()); + ctrWriteGroupMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GROUP_MOD.toString()); + ctrWriteMeterMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.METER_MOD.toString()); + ctrWriteQueueGetConfigReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.QUEUE_GET_CONFIG_REPLY.toString()); + ctrWriteQueueGetConfigRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.QUEUE_GET_CONFIG_REQUEST.toString()); + ctrWriteRoleReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ROLE_REPLY.toString()); + ctrWriteRoleRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ROLE_REQUEST.toString()); + ctrWriteSetAsync = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.SET_ASYNC.toString()); + ctrWriteTableMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.TABLE_MOD.toString()); + + // Register Read Counters + // + hierarchy = "/read"; + + registerCounterLocal(counters, + hierarchy, + stringId, + ""); + ctrReadHello = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.HELLO.toString()); + ctrReadError = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ERROR.toString()); + ctrReadEchoRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ECHO_REQUEST.toString()); + ctrReadEchoReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ECHO_REPLY.toString()); + ctrReadExperimenter = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.EXPERIMENTER.toString()); + ctrReadFeaturesRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FEATURES_REQUEST.toString()); + ctrReadFeaturesReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FEATURES_REPLY.toString()); + ctrReadGetConfigRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_CONFIG_REQUEST.toString()); + ctrReadGetConfigReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_CONFIG_REPLY.toString()); + ctrReadSetConfig = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.SET_CONFIG.toString()); + ctrReadPacketIn = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PACKET_IN.toString()); + ctrReadPacketOut = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PACKET_OUT.toString()); + ctrReadFlowRemoved = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FLOW_REMOVED.toString()); + ctrReadPortStatus = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PORT_STATUS.toString()); + ctrReadFlowMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.FLOW_MOD.toString()); + ctrReadPortMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.PORT_MOD.toString()); + ctrReadStatsRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.STATS_REQUEST.toString()); + ctrReadStatsReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.STATS_REPLY.toString()); + ctrReadBarrierRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.BARRIER_REQUEST.toString()); + ctrReadBarrierReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.BARRIER_REPLY.toString()); + ctrReadGetAsyncReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_ASYNC_REPLY.toString()); + ctrReadGetAsyncRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GET_ASYNC_REQUEST.toString()); + ctrReadGroupMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.GROUP_MOD.toString()); + ctrReadMeterMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.METER_MOD.toString()); + ctrReadQueueGetConfigReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.QUEUE_GET_CONFIG_REPLY.toString()); + ctrReadQueueGetConfigRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.QUEUE_GET_CONFIG_REQUEST.toString()); + ctrReadRoleReply = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ROLE_REPLY.toString()); + ctrReadRoleRequest = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.ROLE_REQUEST.toString()); + ctrReadSetAsync = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.SET_ASYNC.toString()); + ctrReadTableMod = + registerCounterLocal(counters, + hierarchy, + stringId, + OFType.TABLE_MOD.toString()); + } + + /** + * Update Write Counters for Open flow messages + * @param ofm openflow message + */ + public void updateWriteStats(OFMessage ofm) { + switch(ofm.getType()){ + case BARRIER_REPLY: + ctrWriteBarrierReply.increment(); + break; + + case BARRIER_REQUEST: + ctrWriteBarrierRequest.increment(); + break; + + case ECHO_REPLY: + ctrWriteEchoReply.increment(); + break; + + case ECHO_REQUEST: + ctrWriteEchoRequest.increment(); + break; + + case ERROR: + ctrWriteError.increment(); + break; + + case EXPERIMENTER: + ctrWriteExperimenter.increment(); + break; + + case FEATURES_REPLY: + ctrWriteFeaturesReply.increment(); + break; + + case FEATURES_REQUEST: + ctrWriteFeaturesRequest.increment(); + break; + + case FLOW_MOD: + ctrWriteFlowMod.increment(); + break; + + case FLOW_REMOVED: + ctrWriteFlowRemoved.increment(); + break; + + case GET_ASYNC_REPLY: + ctrWriteGetAsyncReply.increment(); + break; + + case GET_ASYNC_REQUEST: + ctrWriteGetAsyncRequest.increment(); + break; + + case GET_CONFIG_REPLY: + ctrWriteGetConfigReply.increment(); + break; + + case GET_CONFIG_REQUEST: + ctrWriteGetConfigRequest.increment(); + break; + + case GROUP_MOD: + ctrWriteGroupMod.increment(); + break; + + case HELLO: + ctrWriteHello.increment(); + break; + + case METER_MOD: + ctrWriteMeterMod.increment(); + break; + + case PACKET_IN: + ctrWritePacketIn.increment(); + break; + + case PACKET_OUT: + ctrWritePacketOut.increment(); + break; + + case PORT_MOD: + ctrWritePortMod.increment(); + break; + + case PORT_STATUS: + ctrWritePortStatus.increment(); + break; + + case QUEUE_GET_CONFIG_REPLY: + ctrWriteQueueGetConfigReply.increment(); + break; + + case QUEUE_GET_CONFIG_REQUEST: + ctrWriteQueueGetConfigRequest.increment(); + break; + + case ROLE_REPLY: + ctrWriteRoleReply.increment(); + break; + + case ROLE_REQUEST: + ctrWriteRoleRequest.increment(); + break; + + case SET_ASYNC: + ctrWriteSetAsync.increment(); + break; + + case SET_CONFIG: + ctrWriteSetConfig.increment(); + break; + + case STATS_REPLY: + ctrWriteStatsReply.increment(); + break; + + case STATS_REQUEST: + ctrWriteStatsRequest.increment(); + break; + + case TABLE_MOD: + ctrWriteTableMod.increment(); + break; + + default: + logger.warn(ofm.getType().toString() + + ": Invalid OpenFlow Messaqe!"); + break; + } + } + + /** + * Update Read openflow counters for this connection + * @param ofm Open Flow Message + */ + public void updateReadStats(OFMessage ofm){ + switch(ofm.getType()){ + case BARRIER_REPLY: + ctrReadBarrierReply.increment(); + break; + + case BARRIER_REQUEST: + ctrReadBarrierRequest.increment(); + break; + + case ECHO_REPLY: + ctrReadEchoReply.increment(); + break; + + case ECHO_REQUEST: + ctrReadEchoRequest.increment(); + break; + + case ERROR: + ctrReadError.increment(); + break; + + case EXPERIMENTER: + ctrReadExperimenter.increment(); + break; + + case FEATURES_REPLY: + ctrReadFeaturesReply.increment(); + break; + + case FEATURES_REQUEST: + ctrReadFeaturesRequest.increment(); + break; + + case FLOW_MOD: + ctrReadFlowMod.increment(); + break; + + case FLOW_REMOVED: + ctrReadFlowRemoved.increment(); + break; + + case GET_ASYNC_REPLY: + ctrReadGetAsyncReply.increment(); + break; + + case GET_ASYNC_REQUEST: + ctrReadGetAsyncRequest.increment(); + break; + + case GET_CONFIG_REPLY: + ctrReadGetConfigReply.increment(); + break; + + case GET_CONFIG_REQUEST: + ctrReadGetConfigRequest.increment(); + break; + + case GROUP_MOD: + ctrReadGroupMod.increment(); + break; + + case HELLO: + ctrReadHello.increment(); + break; + + case METER_MOD: + ctrReadMeterMod.increment(); + break; + + case PACKET_IN: + ctrReadPacketIn.increment(); + break; + + case PACKET_OUT: + ctrReadPacketOut.increment(); + break; + + case PORT_MOD: + ctrReadPortMod.increment(); + break; + + case PORT_STATUS: + ctrReadPortStatus.increment(); + break; + + case QUEUE_GET_CONFIG_REPLY: + ctrReadQueueGetConfigReply.increment(); + break; + + case QUEUE_GET_CONFIG_REQUEST: + ctrReadQueueGetConfigRequest.increment(); + break; + + case ROLE_REPLY: + ctrReadRoleReply.increment(); + break; + + case ROLE_REQUEST: + ctrReadRoleRequest.increment(); + break; + + case SET_ASYNC: + ctrReadSetAsync.increment(); + break; + + case SET_CONFIG: + ctrReadSetConfig.increment(); + break; + + case STATS_REPLY: + ctrReadStatsReply.increment(); + break; + + case STATS_REQUEST: + ctrReadStatsRequest.increment(); + break; + + case TABLE_MOD: + ctrReadTableMod.increment(); + break; + + default: + logger.warn(ofm.getType().toString() + + ": Invalid OpenFlow Messaqe!"); + break; + } + } +} diff --git a/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java b/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java new file mode 100644 index 0000000000000000000000000000000000000000..f990f0a451052dfac060673e5bca7b20d6e802ad --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java @@ -0,0 +1,28 @@ +package net.floodlightcontroller.core; + +import org.projectfloodlight.openflow.protocol.OFErrorMsg; +import org.projectfloodlight.openflow.protocol.OFRequest; + +/** raised/reported by Futures in @IOFConnection when a an + * {@link OFErrorMsg} is received in response to a {@link OFRequest} + * sent via {@link OFConnection#writeRequest(OFRequest)} or + * {@link OFConnection#writeStatsRequest(org.projectfloodlight.openflow.protocol.OFStatsRequest)}. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class OFErrorMsgException extends Exception { + private static final long serialVersionUID = 1L; + + private final OFErrorMsg errorMessage; + + public OFErrorMsgException(final OFErrorMsg errorMessage) { + super("OF error received: " + errorMessage.toString()); + this.errorMessage = errorMessage; + } + + /** @return the received OFErrorMsg that caused the error to be raised. + */ + public OFErrorMsg getErrorMessage() { + return errorMessage; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java index c5adf4470355476526cfe896c92195760d5e8d0f..9a0348767c6d7b952cb9496169d3477b180d6865 100644 --- a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java +++ b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java @@ -29,12 +29,12 @@ import java.util.concurrent.ScheduledExecutorService; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFType; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -226,9 +226,9 @@ public class OFMessageFilterManager OFPacketOut p = (OFPacketOut) m; // No MAC match if packetOut doesn't have the packet. - if (p.getPacketData() == null) return null; + if (p.getData() == null) return null; - eth.deserialize(p.getPacketData(), 0, p.getPacketData().length); + eth.deserialize(p.getData(), 0, p.getData().length); } else if (m.getType() == OFType.FLOW_MOD) { // flow-mod can't be matched by mac. return null; diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java new file mode 100644 index 0000000000000000000000000000000000000000..38b5ddaa6b2bb7a49a3a31deadb1b21cd2719a94 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java @@ -0,0 +1,1131 @@ +/** +* Copyright 2012, Big Switch Networks, Inc. +* Originally created by David Erickson, Stanford University +* +* 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.core; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import javax.annotation.Nonnull; + +import net.floodlightcontroller.core.annotations.LogMessageDoc; +import net.floodlightcontroller.core.internal.IOFSwitchManager; +import net.floodlightcontroller.core.util.AppCookie; +import net.floodlightcontroller.core.util.URIUtil; + +import org.projectfloodlight.openflow.protocol.OFActionType; +import org.projectfloodlight.openflow.protocol.OFBsnControllerConnection; +import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionState; +import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply; +import org.projectfloodlight.openflow.protocol.OFCapabilities; +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFFlowWildcards; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; +import org.projectfloodlight.openflow.protocol.OFPortReason; +import org.projectfloodlight.openflow.protocol.OFPortState; +import org.projectfloodlight.openflow.protocol.OFPortStatus; +import org.projectfloodlight.openflow.protocol.OFRequest; +import org.projectfloodlight.openflow.protocol.OFStatsReply; +import org.projectfloodlight.openflow.protocol.OFStatsRequest; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFAuxId; +import org.projectfloodlight.openflow.types.OFPort; + +import net.floodlightcontroller.util.LinkedHashSetWrapper; +import net.floodlightcontroller.util.OrderedCollection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.ListenableFuture; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * This is the internal representation of an openflow switch. + */ +public class OFSwitch implements IOFSwitchBackend { + protected static final Logger log = + LoggerFactory.getLogger(OFSwitch.class); + + protected final ConcurrentMap<Object, Object> attributes; + protected final IOFSwitchManager switchManager; + + /* Switch features from initial featuresReply */ + protected Set<OFCapabilities> capabilities; + protected long buffers; + protected Set<OFActionType> actions; + protected short tables; + protected final DatapathId datapathId; + + private boolean startDriverHandshakeCalled = false; + private final Map<OFAuxId, IOFConnectionBackend> connections; + private volatile Map<URI, Map<OFAuxId, OFBsnControllerConnection>> controllerConnections; + protected OFFactory factory; + + /** + * Members hidden from subclasses + */ + private final PortManager portManager; + + private volatile boolean connected; + + private volatile OFControllerRole role; + + private boolean flowTableFull = false; + + protected SwitchDescription description; + + private GenTableMap genTableMap; + + private SwitchStatus status; + + public static final int OFSWITCH_APP_ID = ident(5); + + static { + AppCookie.registerApp(OFSwitch.OFSWITCH_APP_ID, "switch"); + } + + public OFSwitch(IOFConnectionBackend connection, @Nonnull OFFactory factory, @Nonnull IOFSwitchManager switchManager, + @Nonnull DatapathId datapathId) { + if(connection == null) + throw new NullPointerException("connection must not be null"); + if(!connection.getAuxId().equals(OFAuxId.MAIN)) + throw new IllegalArgumentException("connection must be the main connection"); + if(factory == null) + throw new NullPointerException("factory must not be null"); + if(switchManager == null) + throw new NullPointerException("switchManager must not be null"); + + this.connected = true; + this.factory = factory; + this.switchManager = switchManager; + this.datapathId = datapathId; + this.attributes = new ConcurrentHashMap<Object, Object>(); + this.role = null; + this.description = new SwitchDescription(); + this.portManager = new PortManager(); + this.genTableMap = GenTableMap.empty(); + this.status = SwitchStatus.HANDSHAKE; + + // Connections + this.connections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>(); + this.connections.put(connection.getAuxId(), connection); + + // Switch's controller connection + this.controllerConnections = ImmutableMap.of(); + + // Defaults properties for an ideal switch + this.setAttribute(PROP_FASTWILDCARDS, EnumSet.allOf(OFFlowWildcards.class)); + this.setAttribute(PROP_SUPPORTS_OFPP_FLOOD, Boolean.TRUE); + this.setAttribute(PROP_SUPPORTS_OFPP_TABLE, Boolean.TRUE); + } + + private static int ident(int i) { + return i; + } + + @Override + public OFFactory getOFFactory() { + return factory; + } + + /** + * Manages the ports of this switch. + * + * Provides methods to query and update the stored ports. The class ensures + * that every port name and port number is unique. When updating ports + * the class checks if port number <-> port name mappings have change due + * to the update. If a new port P has number and port that are inconsistent + * with the previous mapping(s) the class will delete all previous ports + * with name or number of the new port and then add the new port. + * + * Port names are stored as-is but they are compared case-insensitive + * + * The methods that change the stored ports return a list of + * PortChangeEvents that represent the changes that have been applied + * to the port list so that IOFSwitchListeners can be notified about the + * changes. + * + * Implementation notes: + * - We keep several different representations of the ports to allow for + * fast lookups + * - Ports are stored in unchangeable lists. When a port is modified new + * data structures are allocated. + * - We use a read-write-lock for synchronization, so multiple readers are + * allowed. + */ + protected static class PortManager { + private final ReentrantReadWriteLock lock; + private List<OFPortDesc> portList; + private List<OFPortDesc> enabledPortList; + private List<OFPort> enabledPortNumbers; + private Map<OFPort,OFPortDesc> portsByNumber; + private Map<String,OFPortDesc> portsByName; + + public PortManager() { + this.lock = new ReentrantReadWriteLock(); + this.portList = Collections.emptyList(); + this.enabledPortList = Collections.emptyList(); + this.enabledPortNumbers = Collections.emptyList(); + this.portsByName = Collections.emptyMap(); + this.portsByNumber = Collections.emptyMap(); + } + + /** + * Set the internal data structure storing this switch's port + * to the ports specified by newPortsByNumber + * + * CALLER MUST HOLD WRITELOCK + * + * @param newPortsByNumber + * @throws IllegaalStateException if called without holding the + * writelock + */ + private void updatePortsWithNewPortsByNumber( + Map<OFPort,OFPortDesc> newPortsByNumber) { + if (!lock.writeLock().isHeldByCurrentThread()) { + throw new IllegalStateException("Method called without " + + "holding writeLock"); + } + Map<String,OFPortDesc> newPortsByName = + new HashMap<String, OFPortDesc>(); + List<OFPortDesc> newPortList = + new ArrayList<OFPortDesc>(); + List<OFPortDesc> newEnabledPortList = + new ArrayList<OFPortDesc>(); + List<OFPort> newEnabledPortNumbers = new ArrayList<OFPort>(); + + for(OFPortDesc p: newPortsByNumber.values()) { + newPortList.add(p); + newPortsByName.put(p.getName().toLowerCase(), p); + if (p.getState().contains(OFPortState.LIVE)) { + newEnabledPortList.add(p); + newEnabledPortNumbers.add(p.getPortNo()); + } + } + portsByName = Collections.unmodifiableMap(newPortsByName); + portsByNumber = + Collections.unmodifiableMap(newPortsByNumber); + enabledPortList = + Collections.unmodifiableList(newEnabledPortList); + enabledPortNumbers = + Collections.unmodifiableList(newEnabledPortNumbers); + portList = Collections.unmodifiableList(newPortList); + } + + /** + * Handle a OFPortStatus delete message for the given port. + * Updates the internal port maps/lists of this switch and returns + * the PortChangeEvents caused by the delete. If the given port + * exists as it, it will be deleted. If the name<->number for the + * given port is inconsistent with the ports stored by this switch + * the method will delete all ports with the number or name of the + * given port. + * + * This method will increment error/warn counters and log + * + * @param delPort the port from the port status message that should + * be deleted. + * @return ordered collection of port changes applied to this switch + */ + private OrderedCollection<PortChangeEvent> + handlePortStatusDelete(OFPortDesc delPort) { + OrderedCollection<PortChangeEvent> events = + new LinkedHashSetWrapper<PortChangeEvent>(); + lock.writeLock().lock(); + try { + Map<OFPort,OFPortDesc> newPortByNumber = + new HashMap<OFPort, OFPortDesc>(portsByNumber); + OFPortDesc prevPort = + portsByNumber.get(delPort.getPortNo()); + if (prevPort == null) { + // so such port. Do we have a port with the name? + prevPort = portsByName.get(delPort.getName()); + if (prevPort != null) { + newPortByNumber.remove(prevPort.getPortNo()); + events.add(new PortChangeEvent(prevPort, + PortChangeType.DELETE)); + } + } else if (prevPort.getName().equals(delPort.getName())) { + // port exists with consistent name-number mapping + newPortByNumber.remove(delPort.getPortNo()); + events.add(new PortChangeEvent(delPort, + PortChangeType.DELETE)); + } else { + // port with same number exists but its name differs. This + // is weird. The best we can do is to delete the existing + // port(s) that have delPort's name and number. + newPortByNumber.remove(delPort.getPortNo()); + events.add(new PortChangeEvent(prevPort, + PortChangeType.DELETE)); + // is there another port that has delPort's name? + prevPort = portsByName.get(delPort.getName().toLowerCase()); + if (prevPort != null) { + newPortByNumber.remove(prevPort.getPortNo()); + events.add(new PortChangeEvent(prevPort, + PortChangeType.DELETE)); + } + } + updatePortsWithNewPortsByNumber(newPortByNumber); + return events; + } finally { + lock.writeLock().unlock(); + } + } + + /** + * Handle a OFPortStatus message, update the internal data structures + * that store ports and return the list of OFChangeEvents. + * + * This method will increment error/warn counters and log + * + * @param ps + * @return + */ + @SuppressFBWarnings(value="SF_SWITCH_FALLTHROUGH") + public OrderedCollection<PortChangeEvent> handlePortStatusMessage(OFPortStatus ps) { + if (ps == null) { + throw new NullPointerException("OFPortStatus message must " + + "not be null"); + } + lock.writeLock().lock(); + try { + OFPortDesc port = ps.getDesc(); + OFPortReason reason = ps.getReason(); + if (reason == null) { + throw new IllegalArgumentException("Unknown PortStatus " + + "reason code " + ps.getReason()); + } + + if (log.isDebugEnabled()) { + log.debug("Handling OFPortStatus: {} for {}", + reason, String.format("%s (%d)", port.getName(), port.getPortNo().getPortNumber())); + } + + if (reason == OFPortReason.DELETE) + return handlePortStatusDelete(port); + + // We handle ADD and MODIFY the same way. Since OpenFlow + // doesn't specify what uniquely identifies a port the + // notion of ADD vs. MODIFY can also be hazy. So we just + // compare the new port to the existing ones. + Map<OFPort,OFPortDesc> newPortByNumber = + new HashMap<OFPort, OFPortDesc>(portsByNumber); + OrderedCollection<PortChangeEvent> events = getSinglePortChanges(port); + for (PortChangeEvent e: events) { + switch(e.type) { + case DELETE: + newPortByNumber.remove(e.port.getPortNo()); + break; + case ADD: + if (reason != OFPortReason.ADD) { + // weird case + } + // fall through + case DOWN: + case OTHER_UPDATE: + case UP: + // update or add the port in the map + newPortByNumber.put(e.port.getPortNo(), e.port); + break; + } + } + updatePortsWithNewPortsByNumber(newPortByNumber); + return events; + } finally { + lock.writeLock().unlock(); + } + + } + + /** + * Given a new or modified port newPort, returns the list of + * PortChangeEvents to "transform" the current ports stored by + * this switch to include / represent the new port. The ports stored + * by this switch are <b>NOT</b> updated. + * + * This method acquires the readlock and is thread-safe by itself. + * Most callers will need to acquire the write lock before calling + * this method though (if the caller wants to update the ports stored + * by this switch) + * + * @param newPort the new or modified port. + * @return the list of changes + */ + public OrderedCollection<PortChangeEvent> + getSinglePortChanges(OFPortDesc newPort) { + lock.readLock().lock(); + try { + OrderedCollection<PortChangeEvent> events = + new LinkedHashSetWrapper<PortChangeEvent>(); + // Check if we have a port by the same number in our + // old map. + OFPortDesc prevPort = + portsByNumber.get(newPort.getPortNo()); + if (newPort.equals(prevPort)) { + // nothing has changed + return events; + } + + if (prevPort != null && + prevPort.getName().equals(newPort.getName())) { + // A simple modify of a exiting port + // A previous port with this number exists and it's name + // also matches the new port. Find the differences + if (prevPort.getState().contains(OFPortState.LIVE) && !newPort.getState().contains(OFPortState.LIVE)) { + events.add(new PortChangeEvent(newPort, + PortChangeType.DOWN)); + } else if (!prevPort.getState().contains(OFPortState.LIVE) && newPort.getState().contains(OFPortState.LIVE)) { + events.add(new PortChangeEvent(newPort, + PortChangeType.UP)); + } else { + events.add(new PortChangeEvent(newPort, + PortChangeType.OTHER_UPDATE)); + } + return events; + } + + if (prevPort != null) { + // There exists a previous port with the same port + // number but the port name is different (otherwise we would + // never have gotten here) + // Remove the port. Name-number mapping(s) have changed + events.add(new PortChangeEvent(prevPort, + PortChangeType.DELETE)); + } + + // We now need to check if there exists a previous port sharing + // the same name as the new/updated port. + prevPort = portsByName.get(newPort.getName().toLowerCase()); + if (prevPort != null) { + // There exists a previous port with the same port + // name but the port number is different (otherwise we + // never have gotten here). + // Remove the port. Name-number mapping(s) have changed + events.add(new PortChangeEvent(prevPort, + PortChangeType.DELETE)); + } + + // We always need to add the new port. Either no previous port + // existed or we just deleted previous ports with inconsistent + // name-number mappings + events.add(new PortChangeEvent(newPort, PortChangeType.ADD)); + return events; + } finally { + lock.readLock().unlock(); + } + } + + /** + * Compare the current ports of this switch to the newPorts list and + * return the changes that would be applied to transfort the current + * ports to the new ports. No internal data structures are updated + * see {@link #compareAndUpdatePorts(List, boolean)} + * + * @param newPorts the list of new ports + * @return The list of differences between the current ports and + * newPortList + */ + public OrderedCollection<PortChangeEvent> + comparePorts(Collection<OFPortDesc> newPorts) { + return compareAndUpdatePorts(newPorts, false); + } + + /** + * Compare the current ports of this switch to the newPorts list and + * return the changes that would be applied to transform the current + * ports to the new ports. No internal data structures are updated + * see {@link #compareAndUpdatePorts(List, boolean)} + * + * @param newPorts the list of new ports + * @return The list of differences between the current ports and + * newPortList + */ + public OrderedCollection<PortChangeEvent> + updatePorts(Collection<OFPortDesc> newPorts) { + return compareAndUpdatePorts(newPorts, true); + } + + /** + * Compare the current ports stored in this switch instance with the + * new port list given and return the differences in the form of + * PortChangeEvents. If the doUpdate flag is true, newPortList will + * replace the current list of this switch (and update the port maps) + * + * Implementation note: + * Since this method can optionally modify the current ports and + * since it's not possible to upgrade a read-lock to a write-lock + * we need to hold the write-lock for the entire operation. If this + * becomes a problem and if compares() are common we can consider + * splitting in two methods but this requires lots of code duplication + * + * @param newPorts the list of new ports. + * @param doUpdate If true the newPortList will replace the current + * port list for this switch. If false this switch will not be changed. + * @return The list of differences between the current ports and + * newPorts + * @throws NullPointerException if newPortsList is null + * @throws IllegalArgumentException if either port names or port numbers + * are duplicated in the newPortsList. + */ + private OrderedCollection<PortChangeEvent> compareAndUpdatePorts( + Collection<OFPortDesc> newPorts, + boolean doUpdate) { + if (newPorts == null) { + throw new NullPointerException("newPortsList must not be null"); + } + lock.writeLock().lock(); + try { + OrderedCollection<PortChangeEvent> events = + new LinkedHashSetWrapper<PortChangeEvent>(); + + Map<OFPort,OFPortDesc> newPortsByNumber = + new HashMap<OFPort, OFPortDesc>(); + Map<String,OFPortDesc> newPortsByName = + new HashMap<String, OFPortDesc>(); + List<OFPortDesc> newEnabledPortList = + new ArrayList<OFPortDesc>(); + List<OFPort> newEnabledPortNumbers = + new ArrayList<OFPort>(); + List<OFPortDesc> newPortsList = + new ArrayList<OFPortDesc>(newPorts); + + for (OFPortDesc p: newPortsList) { + if (p == null) { + throw new NullPointerException("portList must not " + + "contain null values"); + } + + // Add the port to the new maps and lists and check + // that every port is unique + OFPortDesc duplicatePort; + duplicatePort = newPortsByNumber.put(p.getPortNo(), p); + if (duplicatePort != null) { + String msg = String.format("Cannot have two ports " + + "with the same number: %s <-> %s", + String.format("%s (%d)", p.getName(), p.getPortNo().getPortNumber()), + String.format("%s (%d)", duplicatePort.getName(), duplicatePort.getPortNo().getPortNumber())); + throw new IllegalArgumentException(msg); + } + duplicatePort = + newPortsByName.put(p.getName().toLowerCase(), p); + if (duplicatePort != null) { + String msg = String.format("Cannot have two ports " + + "with the same name: %s <-> %s", + String.format("%s (%d)", p.getName(), p.getPortNo().getPortNumber()), + String.format("%s (%d)", duplicatePort.getName(), duplicatePort.getPortNo().getPortNumber())); + throw new IllegalArgumentException(msg); + } + if (p.getState().contains(OFPortState.LIVE)) { + newEnabledPortList.add(p); + newEnabledPortNumbers.add(p.getPortNo()); + } + + // get changes + events.addAll(getSinglePortChanges(p)); + } + // find deleted ports + // We need to do this after looping through all the new ports + // to we can handle changed name<->number mappings correctly + // We could pull it into the loop of we address this but + // it's probably not worth it + for (OFPortDesc oldPort: this.portList) { + if (!newPortsByNumber.containsKey(oldPort.getPortNo())) { + PortChangeEvent ev = + new PortChangeEvent(oldPort, + PortChangeType.DELETE); + events.add(ev); + } + } + + + if (doUpdate) { + portsByName = Collections.unmodifiableMap(newPortsByName); + portsByNumber = + Collections.unmodifiableMap(newPortsByNumber); + enabledPortList = + Collections.unmodifiableList(newEnabledPortList); + enabledPortNumbers = + Collections.unmodifiableList(newEnabledPortNumbers); + portList = Collections.unmodifiableList(newPortsList); + } + return events; + } finally { + lock.writeLock().unlock(); + } + } + + public OFPortDesc getPort(String name) { + if (name == null) { + throw new NullPointerException("Port name must not be null"); + } + lock.readLock().lock(); + try { + return portsByName.get(name.toLowerCase()); + } finally { + lock.readLock().unlock(); + } + } + + public OFPortDesc getPort(OFPort portNumber) { + lock.readLock().lock(); + try { + return portsByNumber.get(portNumber); + } finally { + lock.readLock().unlock(); + } + } + + public List<OFPortDesc> getPorts() { + lock.readLock().lock(); + try { + return portList; + } finally { + lock.readLock().unlock(); + } + } + + public List<OFPortDesc> getEnabledPorts() { + lock.readLock().lock(); + try { + return enabledPortList; + } finally { + lock.readLock().unlock(); + } + } + + public List<OFPort> getEnabledPortNumbers() { + lock.readLock().lock(); + try { + return enabledPortNumbers; + } finally { + lock.readLock().unlock(); + } + } + } + + @Override + public boolean attributeEquals(String name, Object other) { + Object attr = this.attributes.get(name); + if (attr == null) + return false; + return attr.equals(other); + } + + @Override + public Object getAttribute(String name) { + // returns null if key doesn't exist + return this.attributes.get(name); + } + + @Override + public void setAttribute(String name, Object value) { + this.attributes.put(name, value); + return; + } + + @Override + public Object removeAttribute(String name) { + return this.attributes.remove(name); + } + + @Override + public boolean hasAttribute(String name) { + return this.attributes.containsKey(name); + } + + @Override + public void registerConnection(IOFConnectionBackend connection) { + this.connections.put(connection.getAuxId(), connection); + } + + + @Override + public ImmutableList<IOFConnection> getConnections() { + return ImmutableList.<IOFConnection> copyOf(this.connections.values()); + } + + @Override + public void removeConnections() { + this.connections.clear(); + } + + @Override + public void removeConnection(IOFConnectionBackend connection) { + this.connections.remove(connection.getAuxId()); + } + + @Override + public void write(OFMessage m) { + connections.get(OFAuxId.MAIN).write(m); + } + + /** + * Gets a connection specified by aux Id. + * @param auxId the specified aux id for the connection desired. + * @return the aux connection specified by the auxId + */ + public IOFConnection getConnection(OFAuxId auxId) { + IOFConnection connection = this.connections.get(auxId); + if(connection == null){ + throw new IllegalArgumentException("OF Connection for " + this + " with " + auxId + " does not exist."); + } + return connection; + } + + public IOFConnection getConnection(LogicalOFMessageCategory category) { + if(switchManager.isCategoryRegistered(category)){ + return getConnection(category.getAuxId()); + } + else{ + throw new IllegalArgumentException(category + " is not registered with the floodlight provider service."); + } + } + + @Override + public void write(OFMessage m, LogicalOFMessageCategory category) { + this.getConnection(category).write(m); + } + + @Override + public void write(Iterable<OFMessage> msglist, LogicalOFMessageCategory category) { + this.getConnection(category).write(msglist); + } + + @Override + public OFConnection getConnectionByCategory(LogicalOFMessageCategory category){ + return (OFConnection) this.getConnection(category); + } + + @Override + public <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request, LogicalOFMessageCategory category) { + return getConnection(category).writeRequest(request); + } + + @Override + public <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request) { + return connections.get(OFAuxId.MAIN).writeRequest(request); + } + + @Override + @LogMessageDoc(level="WARN", + message="Sending OF message that modifies switch " + + "state while in the slave role: {switch}", + explanation="An application has sent a message to a switch " + + "that is not valid when the switch is in a slave role", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) + public void write(Iterable<OFMessage> msglist) { + connections.get(OFAuxId.MAIN).write(msglist); + } + + @Override + public void disconnect() { + + // Iterate through connections and perform cleanup + for(Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()){ + entry.getValue().disconnect(); + this.connections.remove(entry.getKey()); + } + + connected = false; + } + + @Override + public void setFeaturesReply(OFFeaturesReply featuresReply) { + if (portManager.getPorts().isEmpty() && featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) { + /* ports are updated via port status message, so we + * only fill in ports on initial connection. + */ + List<OFPortDesc> OFPortDescs = featuresReply.getPorts(); + portManager.updatePorts(OFPortDescs); + } + this.capabilities = featuresReply.getCapabilities(); + this.buffers = featuresReply.getNBuffers(); + + if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0 ) { + // FIXME:LOJI: OF1.3 has per table actions. This needs to be modeled / handled here + this.actions = featuresReply.getActions(); + } + this.tables = featuresReply.getNTables(); + } + + @Override + public void setPortDescStats(OFPortDescStatsReply reply) { + /* ports are updated via port status message, so we + * only fill in ports on initial connection. + */ + List<OFPortDesc> OFPortDescs = reply.getEntries(); + portManager.updatePorts(OFPortDescs); + } + + @Override + public Collection<OFPortDesc> getEnabledPorts() { + return portManager.getEnabledPorts(); + } + + @Override + public Collection<OFPort> getEnabledPortNumbers() { + return portManager.getEnabledPortNumbers(); + } + + @Override + public OFPortDesc getPort(OFPort portNumber) { + return portManager.getPort(portNumber); + } + + @Override + public OFPortDesc getPort(String portName) { + return portManager.getPort(portName); + } + + @Override + public OrderedCollection<PortChangeEvent> + processOFPortStatus(OFPortStatus ps) { + return portManager.handlePortStatusMessage(ps); + } + + @Override + public Collection<OFPortDesc> getSortedPorts() { + // FIXME: Hopefully BigDB will handle this automatically soon (or not + // have the sorting requirement), in which case we could get rid of this + List<OFPortDesc> sortedPorts = + new ArrayList<OFPortDesc>(portManager.getPorts()); + Collections.sort(sortedPorts, new Comparator<OFPortDesc>() { + @Override + public int compare(OFPortDesc o1, OFPortDesc o2) { + String name1 = o1.getName(); + String name2 = o2.getName(); + return name1.compareToIgnoreCase(name2); + } + }); + return sortedPorts; + } + + @Override + public Collection<OFPortDesc> getPorts() { + return portManager.getPorts(); + } + + @Override + public OrderedCollection<PortChangeEvent> + comparePorts(Collection<OFPortDesc> ports) { + return portManager.comparePorts(ports); + } + + @Override + public OrderedCollection<PortChangeEvent> + setPorts(Collection<OFPortDesc> ports) { + return portManager.updatePorts(ports); + } + + @Override + public boolean portEnabled(OFPort portNumber) { + OFPortDesc p = portManager.getPort(portNumber); + if (p == null) return false; + return p.getState().contains(OFPortState.LIVE); + } + + @Override + public boolean portEnabled(String portName) { + OFPortDesc p = portManager.getPort(portName); + if (p == null) return false; + return p.getState().contains(OFPortState.LIVE); + } + + @Override + public DatapathId getId() { + if (datapathId == null) + throw new RuntimeException("Features reply has not yet been set"); + return datapathId; + } + + @Override + public String getStringId() { + // FIXME: Should get rid of this + return getId().toString(); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "OFSwitchBase DPID[" + ((datapathId != null) ? datapathId.toString() : "?") + "]"; + } + + @Override + public ConcurrentMap<Object, Object> getAttributes() { + return this.attributes; + } + + @Override + public Date getConnectedSince() { + return this.connections.get(OFAuxId.MAIN).getConnectedSince(); + } + + @Override + public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest(OFStatsRequest<REPLY> request) { + return connections.get(OFAuxId.MAIN).writeStatsRequest(request); + } + + @Override + public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest(OFStatsRequest<REPLY> request, LogicalOFMessageCategory category) { + return getConnection(category).writeStatsRequest(request); + } + + @Override + public void cancelAllPendingRequests() { + for(Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()){ + entry.getValue().cancelAllPendingRequests(); + } + } + + // If any connections are down consider a switch disconnected + @Override + public boolean isConnected() { + return connected; + } + + @Override + public boolean isActive() { + // no lock needed since we use volatile + return isConnected() && this.role == OFControllerRole.ROLE_MASTER; + } + + @Override + public OFControllerRole getControllerRole() { + return role; + } + + @Override + public void setControllerRole(OFControllerRole role) { + this.role = role; + } + + @Override + public void flush() { + for(Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()){ + entry.getValue().flush(); + } + } + + /** + * Get the IP Address for the switch + * @return the inet address + */ + @Override + public SocketAddress getInetAddress() { + return connections.get(OFAuxId.MAIN).getRemoteInetAddress(); + } + + @Override + public long getBuffers() { + return buffers; + } + + + @Override + public Set<OFActionType> getActions() { + return actions; + } + + + @Override + public Set<OFCapabilities> getCapabilities() { + return capabilities; + } + + + @Override + public short getTables() { + return tables; + } + + @Override + public SwitchDescription getSwitchDescription() { + return description; + } + + @Override + @LogMessageDoc(level="WARN", + message="Switch {switch} flow table is full", + explanation="The controller received flow table full " + + "message from the switch, could be caused by increased " + + "traffic pattern", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) + public void setTableFull(boolean isFull) { + if (isFull && !flowTableFull) { + switchManager.addSwitchEvent(this.datapathId, + "SWITCH_FLOW_TABLE_FULL " + + "Table full error from switch", false); + log.warn("Switch {} flow table is full", datapathId.toString()); + } + flowTableFull = isFull; + } + + @Override + public void startDriverHandshake() { + if (startDriverHandshakeCalled) + throw new SwitchDriverSubHandshakeAlreadyStarted(); + startDriverHandshakeCalled = true; + } + + @Override + public boolean isDriverHandshakeComplete() { + if (!startDriverHandshakeCalled) + throw new SwitchDriverSubHandshakeNotStarted(); + return true; + } + + @Override + public void processDriverHandshakeMessage(OFMessage m) { + if (startDriverHandshakeCalled) + throw new SwitchDriverSubHandshakeCompleted(m); + else + throw new SwitchDriverSubHandshakeNotStarted(); + } + + @Override + public GenTableMap getGenTableMap() { + return genTableMap; + } + + @Override + public void setGenTableMap(GenTableMap map) { + this.genTableMap = map; + } + + @Override + public void setSwitchProperties(SwitchDescription description) { + this.description = description; + } + + + @Override + public SwitchStatus getStatus() { + return status; + } + + @Override + public void setStatus(SwitchStatus switchStatus) { + this.status = switchStatus; + } + + /** + * Can the port be turned on without forming a new loop? + * <p> + * <b>FIXME</b> - This API is deprecated and will be removed soon. The + * property is currently not implemented by the platform, so this method + * always returns false. Whether or not a port is safe to use is dependent + * on the application strategy for forwarding traffic. + * + * @param port_num the port number to be tested + * @return always false for now. + */ + @Deprecated + @Override + public boolean isFastPort(OFPort port_num) { + return false; + } + + @Override + public void updateControllerConnections(OFBsnControllerConnectionsReply controllerCxnsReply) { + + // Instantiate clean map, can't use a builder here since we need to call temp.get() + Map<URI,Map<OFAuxId, OFBsnControllerConnection>> temp = new ConcurrentHashMap<URI,Map<OFAuxId, OFBsnControllerConnection>>(); + + List<OFBsnControllerConnection> controllerCxnUpdates = controllerCxnsReply.getConnections(); + for(OFBsnControllerConnection update : controllerCxnUpdates) { + URI uri = URI.create(update.getUri()); + + Map<OFAuxId, OFBsnControllerConnection> cxns = temp.get(uri); + + // Add to nested map + if(cxns != null){ + cxns.put(update.getAuxiliaryId(), update); + } else{ + cxns = new ConcurrentHashMap<OFAuxId, OFBsnControllerConnection>(); + cxns.put(update.getAuxiliaryId(), update); + temp.put(uri, cxns); + } + } + + this.controllerConnections = ImmutableMap.<URI,Map<OFAuxId, OFBsnControllerConnection>>copyOf(temp); + } + + @Override + public boolean hasAnotherMaster() { + + //TODO: refactor get connection to not throw illegal arg exceptions + IOFConnection mainCxn = this.getConnection(OFAuxId.MAIN); + + if(mainCxn != null) { + + // Determine the local URI + InetSocketAddress address = (InetSocketAddress) mainCxn.getLocalInetAddress(); + URI localURI = URIUtil.createURI(address.getHostName(), address.getPort()); + + for(Entry<URI,Map<OFAuxId, OFBsnControllerConnection>> entry : this.controllerConnections.entrySet()) { + + // Don't check our own controller connections + URI uri = entry.getKey(); + if(!localURI.equals(uri)){ + + // We only care for the MAIN connection + Map<OFAuxId, OFBsnControllerConnection> cxns = this.controllerConnections.get(uri); + OFBsnControllerConnection controllerCxn = cxns.get(OFAuxId.MAIN); + + if(controllerCxn != null) { + // If the controller id disconnected or not master we know it is not connected + if(controllerCxn.getState() == OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED + && controllerCxn.getRole() == OFControllerRole.ROLE_MASTER){ + return true; + } + } else { + log.warn("Unable to find controller connection with aux id " + + "MAIN for switch {} on controller with URI {}.", + this, uri); + } + } + } + } + return false; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java deleted file mode 100644 index 1fb321baddd352b137c78e68b99fab388766fd27..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java +++ /dev/null @@ -1,1579 +0,0 @@ -/** -* Copyright 2012, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core; - -import java.io.IOException; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import net.floodlightcontroller.core.IFloodlightProviderService.Role; -import net.floodlightcontroller.core.annotations.LogMessageDoc; -import net.floodlightcontroller.core.annotations.LogMessageDocs; -import net.floodlightcontroller.core.internal.Controller; -import net.floodlightcontroller.core.internal.OFFeaturesReplyFuture; -import net.floodlightcontroller.core.internal.OFStatisticsFuture; -import net.floodlightcontroller.core.util.AppCookie; -import net.floodlightcontroller.core.web.serializers.DPIDSerializer; -import net.floodlightcontroller.debugcounter.IDebugCounter; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException; -import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType; -import net.floodlightcontroller.debugcounter.NullDebugCounter; -import net.floodlightcontroller.devicemanager.SwitchPort; -import net.floodlightcontroller.packet.Ethernet; -import net.floodlightcontroller.routing.ForwardingBase; -import net.floodlightcontroller.threadpool.IThreadPoolService; -import net.floodlightcontroller.util.LinkedHashSetWrapper; -import net.floodlightcontroller.util.MACAddress; -import net.floodlightcontroller.util.OrderedCollection; -import net.floodlightcontroller.util.TimedCache; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; - -import org.jboss.netty.channel.Channel; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPortStatus; -import org.openflow.protocol.OFPortStatus.OFPortReason; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFStatisticsReply; -import org.openflow.protocol.OFStatisticsRequest; -import org.openflow.protocol.OFType; -import org.openflow.protocol.statistics.OFDescriptionStatistics; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.protocol.statistics.OFTableStatistics; -import org.openflow.util.HexString; -import org.openflow.util.U16; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This is the internal representation of an openflow switch. - */ -public abstract class OFSwitchBase implements IOFSwitch { - // TODO: should we really do logging in the class or should we throw - // exception that can then be handled by callers? - protected static final Logger log = LoggerFactory.getLogger(OFSwitchBase.class); - - protected ConcurrentMap<Object, Object> attributes; - protected IFloodlightProviderService floodlightProvider; - protected IThreadPoolService threadPool; - protected IDebugCounterService debugCounters; - // FIXME: Don't use java.util.Date - protected volatile Date connectedSince; - - /* Switch features from initial featuresReply */ - protected int capabilities; - protected int buffers; - protected int actions; - protected byte tables; - protected long datapathId; - protected String stringId; - - protected short accessFlowPriority; - protected short coreFlowPriority; - - private boolean startDriverHandshakeCalled = false; - protected Channel channel; - - /** - * Members hidden from subclasses - */ - private final AtomicInteger transactionIdSource; - private final Map<Integer,OFStatisticsFuture> statsFutureMap; - private final Map<Integer, IOFMessageListener> iofMsgListenersMap; - private final Map<Integer,OFFeaturesReplyFuture> featuresFutureMap; - private volatile boolean connected; - private volatile Role role; - private final TimedCache<Long> timedCache; - private final ConcurrentMap<Short, AtomicLong> portBroadcastCacheHitMap; - - private final PortManager portManager; - - // Private members for throttling - private boolean writeThrottleEnabled = false; - protected boolean packetInThrottleEnabled = false; // used by test - private int packetInRateThresholdHigh = - Integer.parseInt(System.getProperty("input_threshold", "1000")); - private int packetInRateThresholdLow = 1; - private int packetInRatePerMacThreshold = 50; - private int packetInRatePerPortThreshold = 100; - private long messageCount = 0; - private long messageCountUniqueOFMatch = 0; - private long lastMessageTime; - private int currentRate = 0; - private TimedCache<OFMatch> ofMatchCache; - private TimedCache<Long> macCache; - private TimedCache<Long> macBlockedCache; - private TimedCache<Short> portCache; - private TimedCache<Short> portBlockedCache; - private boolean flowTableFull = false; - - protected OFDescriptionStatistics description; - - private boolean debugCountersRegistered; - @SuppressWarnings("unused") - private IDebugCounter ctrSwitch, ctrSwitchPktin, ctrSwitchWrite; - private IDebugCounter ctrSwitchPktinDrops, ctrSwitchWriteDrops; - - private static final String PACKAGE = OFSwitchBase.class.getPackage().getName(); - - - protected final static ThreadLocal<Map<IOFSwitch,List<OFMessage>>> local_msg_buffer = - new ThreadLocal<Map<IOFSwitch,List<OFMessage>>>() { - @Override - protected Map<IOFSwitch,List<OFMessage>> initialValue() { - return new HashMap<IOFSwitch,List<OFMessage>>(); - } - }; - - public static final int OFSWITCH_APP_ID = 5; - static { - AppCookie.registerApp(OFSwitchBase.OFSWITCH_APP_ID, "switch"); - } - - public OFSwitchBase() { - this.stringId = null; - this.attributes = new ConcurrentHashMap<Object, Object>(); - this.connectedSince = null; - this.transactionIdSource = new AtomicInteger(); - this.connected = false; - this.statsFutureMap = new ConcurrentHashMap<Integer,OFStatisticsFuture>(); - this.featuresFutureMap = new ConcurrentHashMap<Integer,OFFeaturesReplyFuture>(); - this.iofMsgListenersMap = new ConcurrentHashMap<Integer,IOFMessageListener>(); - this.role = null; - this.timedCache = new TimedCache<Long>(100, 5*1000 ); // 5 seconds interval - this.portBroadcastCacheHitMap = new ConcurrentHashMap<Short, AtomicLong>(); - this.description = new OFDescriptionStatistics(); - this.lastMessageTime = System.currentTimeMillis(); - - this.portManager = new PortManager(); - - // Defaults properties for an ideal switch - this.setAttribute(PROP_FASTWILDCARDS, OFMatch.OFPFW_ALL); - this.setAttribute(PROP_SUPPORTS_OFPP_FLOOD, Boolean.valueOf(true)); - this.setAttribute(PROP_SUPPORTS_OFPP_TABLE, Boolean.valueOf(true)); - if (packetInRateThresholdHigh == 0) { - packetInRateThresholdHigh = Integer.MAX_VALUE; - } else { - packetInRateThresholdLow = packetInRateThresholdHigh / 2; - } - } - - - - /** - * Manages the ports of this switch. - * - * Provides methods to query and update the stored ports. The class ensures - * that every port name and port number is unique. When updating ports - * the class checks if port number <-> port name mappings have change due - * to the update. If a new port P has number and port that are inconsistent - * with the previous mapping(s) the class will delete all previous ports - * with name or number of the new port and then add the new port. - * - * Port names are stored as-is but they are compared case-insensitive - * - * The methods that change the stored ports return a list of - * PortChangeEvents that represent the changes that have been applied - * to the port list so that IOFSwitchListeners can be notified about the - * changes. - * - * Implementation notes: - * - We keep several different representations of the ports to allow for - * fast lookups - * - Ports are stored in unchangeable lists. When a port is modified new - * data structures are allocated. - * - We use a read-write-lock for synchronization, so multiple readers are - * allowed. - */ - protected class PortManager { - private final ReentrantReadWriteLock lock; - private List<ImmutablePort> portList; - private List<ImmutablePort> enabledPortList; - private List<Short> enabledPortNumbers; - private Map<Short,ImmutablePort> portsByNumber; - private Map<String,ImmutablePort> portsByName; - - - - - public PortManager() { - this.lock = new ReentrantReadWriteLock(); - this.portList = Collections.emptyList(); - this.enabledPortList = Collections.emptyList(); - this.enabledPortNumbers = Collections.emptyList(); - this.portsByName = Collections.emptyMap(); - this.portsByNumber = Collections.emptyMap(); - } - - /** - * Set the internal data structure storing this switch's port - * to the ports specified by newPortsByNumber - * - * CALLER MUST HOLD WRITELOCK - * - * @param newPortsByNumber - * @throws IllegaalStateException if called without holding the - * writelock - */ - private void updatePortsWithNewPortsByNumber( - Map<Short,ImmutablePort> newPortsByNumber) { - if (!lock.writeLock().isHeldByCurrentThread()) { - throw new IllegalStateException("Method called without " + - "holding writeLock"); - } - Map<String,ImmutablePort> newPortsByName = - new HashMap<String, ImmutablePort>(); - List<ImmutablePort> newPortList = - new ArrayList<ImmutablePort>(); - List<ImmutablePort> newEnabledPortList = - new ArrayList<ImmutablePort>(); - List<Short> newEnabledPortNumbers = new ArrayList<Short>(); - - for(ImmutablePort p: newPortsByNumber.values()) { - newPortList.add(p); - newPortsByName.put(p.getName().toLowerCase(), p); - if (p.isEnabled()) { - newEnabledPortList.add(p); - newEnabledPortNumbers.add(p.getPortNumber()); - } - } - portsByName = Collections.unmodifiableMap(newPortsByName); - portsByNumber = - Collections.unmodifiableMap(newPortsByNumber); - enabledPortList = - Collections.unmodifiableList(newEnabledPortList); - enabledPortNumbers = - Collections.unmodifiableList(newEnabledPortNumbers); - portList = Collections.unmodifiableList(newPortList); - } - - /** - * Handle a OFPortStatus delete message for the given port. - * Updates the internal port maps/lists of this switch and returns - * the PortChangeEvents caused by the delete. If the given port - * exists as it, it will be deleted. If the name<->number for the - * given port is inconsistent with the ports stored by this switch - * the method will delete all ports with the number or name of the - * given port. - * - * This method will increment error/warn counters and log - * - * @param delPort the port from the port status message that should - * be deleted. - * @return ordered collection of port changes applied to this switch - */ - private OrderedCollection<PortChangeEvent> - handlePortStatusDelete(ImmutablePort delPort) { - lock.writeLock().lock(); - OrderedCollection<PortChangeEvent> events = - new LinkedHashSetWrapper<PortChangeEvent>(); - try { - Map<Short,ImmutablePort> newPortByNumber = - new HashMap<Short, ImmutablePort>(portsByNumber); - ImmutablePort prevPort = - portsByNumber.get(delPort.getPortNumber()); - if (prevPort == null) { - // so such port. Do we have a port with the name? - prevPort = portsByName.get(delPort.getName()); - if (prevPort != null) { - newPortByNumber.remove(prevPort.getPortNumber()); - events.add(new PortChangeEvent(prevPort, - PortChangeType.DELETE)); - } - } else if (prevPort.getName().equals(delPort.getName())) { - // port exists with consistent name-number mapping - newPortByNumber.remove(delPort.getPortNumber()); - events.add(new PortChangeEvent(delPort, - PortChangeType.DELETE)); - } else { - // port with same number exists but its name differs. This - // is weird. The best we can do is to delete the existing - // port(s) that have delPort's name and number. - newPortByNumber.remove(delPort.getPortNumber()); - events.add(new PortChangeEvent(prevPort, - PortChangeType.DELETE)); - // is there another port that has delPort's name? - prevPort = portsByName.get(delPort.getName().toLowerCase()); - if (prevPort != null) { - newPortByNumber.remove(prevPort.getPortNumber()); - events.add(new PortChangeEvent(prevPort, - PortChangeType.DELETE)); - } - } - updatePortsWithNewPortsByNumber(newPortByNumber); - return events; - } finally { - lock.writeLock().unlock(); - } - } - - /** - * Handle a OFPortStatus message, update the internal data structures - * that store ports and return the list of OFChangeEvents. - * - * This method will increment error/warn counters and log - * - * @param ps - * @return - */ - public OrderedCollection<PortChangeEvent> handlePortStatusMessage(OFPortStatus ps) { - if (ps == null) { - throw new NullPointerException("OFPortStatus message must " + - "not be null"); - } - lock.writeLock().lock(); - try { - ImmutablePort port = - ImmutablePort.fromOFPhysicalPort(ps.getDesc()); - OFPortReason reason = OFPortReason.fromReasonCode(ps.getReason()); - if (reason == null) { - throw new IllegalArgumentException("Unknown PortStatus " + - "reason code " + ps.getReason()); - } - - if (log.isDebugEnabled()) { - log.debug("Handling OFPortStatus: {} for {}", - reason, port.toBriefString()); - } - - if (reason == OFPortReason.OFPPR_DELETE) - return handlePortStatusDelete(port); - - // We handle ADD and MODIFY the same way. Since OpenFlow - // doesn't specify what uniquely identifies a port the - // notion of ADD vs. MODIFY can also be hazy. So we just - // compare the new port to the existing ones. - Map<Short,ImmutablePort> newPortByNumber = - new HashMap<Short, ImmutablePort>(portsByNumber); - OrderedCollection<PortChangeEvent> events = getSinglePortChanges(port); - for (PortChangeEvent e: events) { - switch(e.type) { - case DELETE: - newPortByNumber.remove(e.port.getPortNumber()); - break; - case ADD: - if (reason != OFPortReason.OFPPR_ADD) { - // weird case - } - // fall through - case DOWN: - case OTHER_UPDATE: - case UP: - // update or add the port in the map - newPortByNumber.put(e.port.getPortNumber(), e.port); - break; - } - } - updatePortsWithNewPortsByNumber(newPortByNumber); - return events; - } finally { - lock.writeLock().unlock(); - } - - } - - /** - * Given a new or modified port newPort, returns the list of - * PortChangeEvents to "transform" the current ports stored by - * this switch to include / represent the new port. The ports stored - * by this switch are <b>NOT</b> updated. - * - * This method acquires the readlock and is thread-safe by itself. - * Most callers will need to acquire the write lock before calling - * this method though (if the caller wants to update the ports stored - * by this switch) - * - * @param newPort the new or modified port. - * @return the list of changes - */ - public OrderedCollection<PortChangeEvent> - getSinglePortChanges(ImmutablePort newPort) { - lock.readLock().lock(); - try { - OrderedCollection<PortChangeEvent> events = - new LinkedHashSetWrapper<PortChangeEvent>(); - // Check if we have a port by the same number in our - // old map. - ImmutablePort prevPort = - portsByNumber.get(newPort.getPortNumber()); - if (newPort.equals(prevPort)) { - // nothing has changed - return events; - } - - if (prevPort != null && - prevPort.getName().equals(newPort.getName())) { - // A simple modify of a exiting port - // A previous port with this number exists and it's name - // also matches the new port. Find the differences - if (prevPort.isEnabled() && !newPort.isEnabled()) { - events.add(new PortChangeEvent(newPort, - PortChangeType.DOWN)); - } else if (!prevPort.isEnabled() && newPort.isEnabled()) { - events.add(new PortChangeEvent(newPort, - PortChangeType.UP)); - } else { - events.add(new PortChangeEvent(newPort, - PortChangeType.OTHER_UPDATE)); - } - return events; - } - - if (prevPort != null) { - // There exists a previous port with the same port - // number but the port name is different (otherwise we would - // never have gotten here) - // Remove the port. Name-number mapping(s) have changed - events.add(new PortChangeEvent(prevPort, - PortChangeType.DELETE)); - } - - // We now need to check if there exists a previous port sharing - // the same name as the new/updated port. - prevPort = portsByName.get(newPort.getName().toLowerCase()); - if (prevPort != null) { - // There exists a previous port with the same port - // name but the port number is different (otherwise we - // never have gotten here). - // Remove the port. Name-number mapping(s) have changed - events.add(new PortChangeEvent(prevPort, - PortChangeType.DELETE)); - } - - // We always need to add the new port. Either no previous port - // existed or we just deleted previous ports with inconsistent - // name-number mappings - events.add(new PortChangeEvent(newPort, PortChangeType.ADD)); - return events; - } finally { - lock.readLock().unlock(); - } - } - - /** - * Compare the current ports of this switch to the newPorts list and - * return the changes that would be applied to transfort the current - * ports to the new ports. No internal data structures are updated - * see {@link #compareAndUpdatePorts(List, boolean)} - * - * @param newPorts the list of new ports - * @return The list of differences between the current ports and - * newPortList - */ - public OrderedCollection<PortChangeEvent> - comparePorts(Collection<ImmutablePort> newPorts) { - return compareAndUpdatePorts(newPorts, false); - } - - /** - * Compare the current ports of this switch to the newPorts list and - * return the changes that would be applied to transform the current - * ports to the new ports. No internal data structures are updated - * see {@link #compareAndUpdatePorts(List, boolean)} - * - * @param newPorts the list of new ports - * @return The list of differences between the current ports and - * newPortList - */ - public OrderedCollection<PortChangeEvent> - updatePorts(Collection<ImmutablePort> newPorts) { - return compareAndUpdatePorts(newPorts, true); - } - - /** - * Compare the current ports stored in this switch instance with the - * new port list given and return the differences in the form of - * PortChangeEvents. If the doUpdate flag is true, newPortList will - * replace the current list of this switch (and update the port maps) - * - * Implementation note: - * Since this method can optionally modify the current ports and - * since it's not possible to upgrade a read-lock to a write-lock - * we need to hold the write-lock for the entire operation. If this - * becomes a problem and if compares() are common we can consider - * splitting in two methods but this requires lots of code duplication - * - * @param newPorts the list of new ports. - * @param doUpdate If true the newPortList will replace the current - * port list for this switch. If false this switch will not be changed. - * @return The list of differences between the current ports and - * newPorts - * @throws NullPointerException if newPortsList is null - * @throws IllegalArgumentException if either port names or port numbers - * are duplicated in the newPortsList. - */ - private OrderedCollection<PortChangeEvent> compareAndUpdatePorts( - Collection<ImmutablePort> newPorts, - boolean doUpdate) { - if (newPorts == null) { - throw new NullPointerException("newPortsList must not be null"); - } - lock.writeLock().lock(); - try { - OrderedCollection<PortChangeEvent> events = - new LinkedHashSetWrapper<PortChangeEvent>(); - - Map<Short,ImmutablePort> newPortsByNumber = - new HashMap<Short, ImmutablePort>(); - Map<String,ImmutablePort> newPortsByName = - new HashMap<String, ImmutablePort>(); - List<ImmutablePort> newEnabledPortList = - new ArrayList<ImmutablePort>(); - List<Short> newEnabledPortNumbers = - new ArrayList<Short>(); - List<ImmutablePort> newPortsList = - new ArrayList<ImmutablePort>(newPorts); - - for (ImmutablePort p: newPortsList) { - if (p == null) { - throw new NullPointerException("portList must not " + - "contain null values"); - } - - // Add the port to the new maps and lists and check - // that every port is unique - ImmutablePort duplicatePort; - duplicatePort = newPortsByNumber.put(p.getPortNumber(), p); - if (duplicatePort != null) { - String msg = String.format("Cannot have two ports " + - "with the same number: %s <-> %s", - p.toBriefString(), - duplicatePort.toBriefString()); - throw new IllegalArgumentException(msg); - } - duplicatePort = - newPortsByName.put(p.getName().toLowerCase(), p); - if (duplicatePort != null) { - String msg = String.format("Cannot have two ports " + - "with the same name: %s <-> %s", - p.toBriefString(), - duplicatePort.toBriefString()); - throw new IllegalArgumentException(msg); - } - if (p.isEnabled()) { - newEnabledPortList.add(p); - newEnabledPortNumbers.add(p.getPortNumber()); - } - - // get changes - events.addAll(getSinglePortChanges(p)); - } - // find deleted ports - // We need to do this after looping through all the new ports - // to we can handle changed name<->number mappings correctly - // We could pull it into the loop of we address this but - // it's probably not worth it - for (ImmutablePort oldPort: this.portList) { - if (!newPortsByNumber.containsKey(oldPort.getPortNumber())) { - PortChangeEvent ev = - new PortChangeEvent(oldPort, - PortChangeType.DELETE); - events.add(ev); - } - } - - - if (doUpdate) { - portsByName = Collections.unmodifiableMap(newPortsByName); - portsByNumber = - Collections.unmodifiableMap(newPortsByNumber); - enabledPortList = - Collections.unmodifiableList(newEnabledPortList); - enabledPortNumbers = - Collections.unmodifiableList(newEnabledPortNumbers); - portList = Collections.unmodifiableList(newPortsList); - } - return events; - } finally { - lock.writeLock().unlock(); - } - } - - public ImmutablePort getPort(String name) { - if (name == null) { - throw new NullPointerException("Port name must not be null"); - } - lock.readLock().lock(); - try { - return portsByName.get(name.toLowerCase()); - } finally { - lock.readLock().unlock(); - } - } - - public ImmutablePort getPort(Short portNumber) { - lock.readLock().lock(); - try { - return portsByNumber.get(portNumber); - } finally { - lock.readLock().unlock(); - } - } - - public List<ImmutablePort> getPorts() { - lock.readLock().lock(); - try { - return portList; - } finally { - lock.readLock().unlock(); - } - } - - public List<ImmutablePort> getEnabledPorts() { - lock.readLock().lock(); - try { - return enabledPortList; - } finally { - lock.readLock().unlock(); - } - } - - public List<Short> getEnabledPortNumbers() { - lock.readLock().lock(); - try { - return enabledPortNumbers; - } finally { - lock.readLock().unlock(); - } - } - } - - - @Override - public boolean attributeEquals(String name, Object other) { - Object attr = this.attributes.get(name); - if (attr == null) - return false; - return attr.equals(other); - } - - - @Override - public Object getAttribute(String name) { - // returns null if key doesn't exist - return this.attributes.get(name); - } - - @Override - public void setAttribute(String name, Object value) { - this.attributes.put(name, value); - return; - } - - @Override - public Object removeAttribute(String name) { - return this.attributes.remove(name); - } - - @Override - public boolean hasAttribute(String name) { - return this.attributes.containsKey(name); - } - - @Override - @JsonIgnore - public void setChannel(Channel channel) { - this.channel = channel; - } - - // For driver subclass to set throttling - protected void enableWriteThrottle(boolean enable) { - this.writeThrottleEnabled = enable; - } - - @Override - public boolean isWriteThrottleEnabled() { - return this.writeThrottleEnabled; - } - - @Override - @LogMessageDocs({ - @LogMessageDoc(level="WARN", - message="Drop throttled OF message to switch {switch}", - explanation="The controller is sending more messages" + - "than the switch can handle. Some messages are dropped" + - "to prevent switch outage", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) - }) - public void writeThrottled(OFMessage m, FloodlightContext bc) - throws IOException { - if (channel == null || !isConnected()) - return; - /** - * By default, channel uses an unbounded send queue. Enable throttling - * prevents the queue from growing big. - * - * channel.isWritable() returns true when queue length is less than - * high water mark (64 kbytes). Once exceeded, isWritable() becomes - * false after queue length drops below low water mark (32 kbytes). - */ - if (!writeThrottleEnabled || channel.isWritable()) { - write(m, bc); - } else { - // Let logback duplicate filtering take care of excessive logs - ctrSwitchWriteDrops.updateCounterNoFlush(); - log.warn("Drop throttled OF message to switch {}", this); - } - } - - @Override - public void writeThrottled(List<OFMessage> msglist, FloodlightContext bc) - throws IOException { - if (!writeThrottleEnabled || channel.isWritable()) { - write(msglist, bc); - } else { - // Let logback duplicate filtering take care of excessive logs - ctrSwitchWriteDrops.updateCounterNoFlush(msglist.size()); - log.warn("Drop throttled OF messages to switch {}", this); - } - } - - @Override - public void write(OFMessage m, FloodlightContext bc) { - if (channel == null || !isConnected()) - return; - //throws IOException { - Map<IOFSwitch,List<OFMessage>> msg_buffer_map = local_msg_buffer.get(); - List<OFMessage> msg_buffer = msg_buffer_map.get(this); - if (msg_buffer == null) { - msg_buffer = new ArrayList<OFMessage>(); - msg_buffer_map.put(this, msg_buffer); - } - - this.floodlightProvider.handleOutgoingMessage(this, m, bc); - msg_buffer.add(m); - - if ((msg_buffer.size() >= Controller.BATCH_MAX_SIZE) || - ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) { - this.write(msg_buffer); - msg_buffer.clear(); - } - } - @Override - @LogMessageDoc(level="WARN", - message="Sending OF message that modifies switch " + - "state while in the slave role: {switch}", - explanation="An application has sent a message to a switch " + - "that is not valid when the switch is in a slave role", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) - public void write(List<OFMessage> msglist, - FloodlightContext bc) { - if (channel == null || !isConnected()) - return; - for (OFMessage m : msglist) { - if (role == Role.SLAVE) { - switch (m.getType()) { - case PACKET_OUT: - case FLOW_MOD: - case PORT_MOD: - log.warn("Sending OF message that modifies switch " + - "state while in the slave role: {}", - m.getType().name()); - break; - default: - break; - } - } - this.floodlightProvider.handleOutgoingMessage(this, m, bc); - } - this.write(msglist); - } - - /** - * Not callable by writers, but allow IOFSwitch implementation to override - * @param msglist - * @throws IOException - */ - protected void write(List<OFMessage> msglist) { - if (channel == null || !isConnected()) - return; - this.channel.write(msglist); - } - - @Override - public void disconnectOutputStream() { - if (channel == null) - return; - channel.close(); - } - - @Override - @JsonIgnore - public void setFeaturesReply(OFFeaturesReply featuresReply) { - if (stringId == null) { - /* ports are updated via port status message, so we - * only fill in ports on initial connection. - */ - List<ImmutablePort> immutablePorts = ImmutablePort - .immutablePortListOf(featuresReply.getPorts()); - portManager.updatePorts(immutablePorts); - } - this.datapathId = featuresReply.getDatapathId(); - this.stringId = HexString.toHexString(featuresReply.getDatapathId()); - this.capabilities = featuresReply.getCapabilities(); - this.buffers = featuresReply.getBuffers(); - this.actions = featuresReply.getActions(); - this.tables = featuresReply.getTables(); -} - - @Override - @JsonIgnore - public Collection<ImmutablePort> getEnabledPorts() { - return portManager.getEnabledPorts(); - } - - @Override - @JsonIgnore - public Collection<Short> getEnabledPortNumbers() { - return portManager.getEnabledPortNumbers(); - } - - @Override - public ImmutablePort getPort(short portNumber) { - return portManager.getPort(portNumber); - } - - @Override - public ImmutablePort getPort(String portName) { - return portManager.getPort(portName); - } - - @Override - @JsonIgnore - public OrderedCollection<PortChangeEvent> - processOFPortStatus(OFPortStatus ps) { - return portManager.handlePortStatusMessage(ps); - } - - @Override - @JsonProperty("ports") - public Collection<ImmutablePort> getPorts() { - return portManager.getPorts(); - } - - @Override - public OrderedCollection<PortChangeEvent> - comparePorts(Collection<ImmutablePort> ports) { - return portManager.comparePorts(ports); - } - - @Override - @JsonIgnore - public OrderedCollection<PortChangeEvent> - setPorts(Collection<ImmutablePort> ports) { - return portManager.updatePorts(ports); - } - - @Override - public boolean portEnabled(short portNumber) { - ImmutablePort p = portManager.getPort(portNumber); - if (p == null) return false; - return p.isEnabled(); - } - - @Override - public boolean portEnabled(String portName) { - ImmutablePort p = portManager.getPort(portName); - if (p == null) return false; - return p.isEnabled(); - } - - @Override - @JsonSerialize(using=DPIDSerializer.class) - @JsonProperty("dpid") - public long getId() { - if (this.stringId == null) - throw new RuntimeException("Features reply has not yet been set"); - return this.datapathId; - } - - @JsonIgnore - @Override - public String getStringId() { - return stringId; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - String channelString = - (channel != null) ? channel.getRemoteAddress().toString() : - "?"; - return "OFSwitchBase [" + channelString + " DPID[" + ((stringId != null) ? stringId : "?") + "]]"; - } - - @Override - public ConcurrentMap<Object, Object> getAttributes() { - return this.attributes; - } - - @Override - public Date getConnectedSince() { - return connectedSince; - } - - @JsonIgnore - @Override - public int getNextTransactionId() { - return this.transactionIdSource.incrementAndGet(); - } - - @Override - public void sendStatsQuery(OFStatisticsRequest request, int xid, - IOFMessageListener caller) throws IOException { - request.setXid(xid); - this.iofMsgListenersMap.put(xid, caller); - List<OFMessage> msglist = new ArrayList<OFMessage>(1); - msglist.add(request); - this.write(msglist); - return; - } - - @Override - public Future<List<OFStatistics>> queryStatistics(OFStatisticsRequest request) throws IOException { - request.setXid(getNextTransactionId()); - OFStatisticsFuture future = new OFStatisticsFuture(threadPool, this, request.getXid()); - this.statsFutureMap.put(request.getXid(), future); - List<OFMessage> msglist = new ArrayList<OFMessage>(1); - msglist.add(request); - this.write(msglist); - return future; - } - - @Override - public void deliverStatisticsReply(OFStatisticsReply reply) { - checkForTableStats(reply); - OFStatisticsFuture future = this.statsFutureMap.get(reply.getXid()); - if (future != null) { - future.deliverFuture(this, reply); - // The future will ultimately unregister itself and call - // cancelStatisticsReply - return; - } - /* Transaction id was not found in statsFutureMap.check the other map */ - IOFMessageListener caller = this.iofMsgListenersMap.get(reply.getXid()); - if (caller != null) { - caller.receive(this, reply, null); - } - } - - @LogMessageDocs({ - @LogMessageDoc(level="INFO", - message="Switch {switch} flow table is full", - explanation="The switch flow table at least 98% full, " + - "this requires attention if using reactive flow setup"), - @LogMessageDoc(level="INFO", - message="Switch {switch} flow table capacity back to normal", - explanation="The switch flow table is less than 90% full") - }) - private void checkForTableStats(OFStatisticsReply statReply) { - if (statReply.getStatisticType() != OFStatisticsType.TABLE) { - return; - } - List<? extends OFStatistics> stats = statReply.getStatistics(); - // Assume a single table only - OFStatistics stat = stats.get(0); - if (stat instanceof OFTableStatistics) { - OFTableStatistics tableStat = (OFTableStatistics) stat; - int activeCount = tableStat.getActiveCount(); - int maxEntry = tableStat.getMaximumEntries(); - log.debug("Switch {} active entries {} max entries {}", - new Object[] { this.stringId, activeCount, maxEntry}); - int percentFull = activeCount * 100 / maxEntry; - if (flowTableFull && percentFull < 90) { - log.info("Switch {} flow table capacity is back to normal", - toString()); - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_FLOW_TABLE_NORMAL < 90% full", false); - } else if (percentFull >= 98) { - log.info("Switch {} flow table is almost full", toString()); - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_FLOW_TABLE_ALMOST_FULL >= 98% full", false); - } - } - } - - - @Override - public void cancelStatisticsReply(int transactionId) { - if (null == this.statsFutureMap.remove(transactionId)) { - this.iofMsgListenersMap.remove(transactionId); - } - } - - @Override - public void cancelAllStatisticsReplies() { - /* we don't need to be synchronized here. Even if another thread - * modifies the map while we're cleaning up the future will eventuall - * timeout */ - for (OFStatisticsFuture f : statsFutureMap.values()) { - f.cancel(true); - } - statsFutureMap.clear(); - iofMsgListenersMap.clear(); - } - - - /** - * @param floodlightProvider the floodlightProvider to set - */ - @JsonIgnore - public void setFloodlightProvider( - IFloodlightProviderService floodlightProvider) { - this.floodlightProvider = floodlightProvider; - } - - @Override - @JsonIgnore - public void setThreadPoolService(IThreadPoolService tp) { - this.threadPool = tp; - } - - @Override - @JsonIgnore - public void setDebugCounterService(IDebugCounterService debugCounters) - throws CounterException { - this.debugCounters = debugCounters; - registerOverloadCounters(); - } - - @JsonIgnore - @Override - public boolean isConnected() { - // no lock needed since we use volatile - return connected; - } - - @JsonIgnore - @Override - public boolean isActive() { - // no lock needed since we use volatile - return isConnected() && this.role == Role.MASTER; - } - - @Override - @JsonIgnore - public void setConnected(boolean connected) { - // No lock needed since we use volatile - if (connected && this.connectedSince == null) - this.connectedSince = new Date(); - else if (!connected) - this.connectedSince = null; - this.connected = connected; - } - - @Override - public Role getHARole() { - return role; - } - - @JsonIgnore - @Override - public void setHARole(Role role) { - this.role = role; - } - - @LogMessageDoc(level="INFO", - message="Switch {switch} flow cleared", - explanation="The switch flow table has been cleared, " + - "this normally happens on switch connection") - @Override - public void clearAllFlowMods() { - if (channel == null || !isConnected()) - return; - // Delete all pre-existing flows - log.info("Clearing all flows on switch {}", this); - OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); - OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD)) - .setMatch(match) - .setCommand(OFFlowMod.OFPFC_DELETE) - .setOutPort(OFPort.OFPP_NONE) - .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); - fm.setXid(getNextTransactionId()); - OFMessage barrierMsg = floodlightProvider.getOFMessageFactory().getMessage( - OFType.BARRIER_REQUEST); - barrierMsg.setXid(getNextTransactionId()); - List<OFMessage> msglist = new ArrayList<OFMessage>(2); - msglist.add(fm); - msglist.add(barrierMsg); - channel.write(msglist); - } - - @Override - public boolean updateBroadcastCache(Long entry, Short port) { - if (timedCache.update(entry)) { - AtomicLong count = portBroadcastCacheHitMap.get(port); - if(count == null) { - AtomicLong newCount = new AtomicLong(0); - AtomicLong retrieved; - if((retrieved = portBroadcastCacheHitMap.putIfAbsent(port, newCount)) == null ) { - count = newCount; - } else { - count = retrieved; - } - } - count.incrementAndGet(); - return true; - } else { - return false; - } - } - - @Override - @JsonIgnore - public Map<Short, Long> getPortBroadcastHits() { - Map<Short, Long> res = new HashMap<Short, Long>(); - for (Map.Entry<Short, AtomicLong> entry : portBroadcastCacheHitMap.entrySet()) { - res.put(entry.getKey(), entry.getValue().get()); - } - return res; - } - - @Override - public void flush() { - Map<IOFSwitch,List<OFMessage>> msg_buffer_map = local_msg_buffer.get(); - List<OFMessage> msglist = msg_buffer_map.get(this); - if ((msglist != null) && (msglist.size() > 0)) { - /* ============================ BIG CAVEAT =============================== - * This code currently works, but relies on undocumented behavior of - * netty. - * - * The method org.jboss.netty.channel.Channel.write(Object) - * (invoked from this.write(List<OFMessage> msg) is currently - * documented to be <emph>asynchronous</emph>. If the method /were/ truely - * asynchronous, this would break our code (because we are clearing the - * msglist right after calling write. - * - * For now, Netty actually invokes the conversion pipeline before doing - * anything asynchronous, so we are safe. But we should probably change - * that behavior. - */ - this.write(msglist); - msglist.clear(); - } - } - - public static void flush_all() { - Map<IOFSwitch,List<OFMessage>> msg_buffer_map = local_msg_buffer.get(); - for (IOFSwitch sw : msg_buffer_map.keySet()) { - sw.flush(); - } - } - - - /** - * Get the IP Address for the switch - * @return the inet address - */ - @Override - @JsonSerialize(using=ToStringSerializer.class) - public SocketAddress getInetAddress() { - if (channel == null) - return null; - return channel.getRemoteAddress(); - } - - @Override - public Future<OFFeaturesReply> querySwitchFeaturesReply() - throws IOException { - OFMessage request = - floodlightProvider.getOFMessageFactory(). - getMessage(OFType.FEATURES_REQUEST); - request.setXid(getNextTransactionId()); - OFFeaturesReplyFuture future = - new OFFeaturesReplyFuture(threadPool, this, request.getXid()); - this.featuresFutureMap.put(request.getXid(), future); - List<OFMessage> msglist = new ArrayList<OFMessage>(1); - msglist.add(request); - this.write(msglist); - return future; - } - - @Override - public void deliverOFFeaturesReply(OFMessage reply) { - OFFeaturesReplyFuture future = this.featuresFutureMap.get(reply.getXid()); - if (future != null) { - future.deliverFuture(this, reply); - // The future will ultimately unregister itself and call - // cancelFeaturesReply - return; - } - log.error("Switch {}: received unexpected featureReply", this); - } - - @Override - public void cancelFeaturesReply(int transactionId) { - this.featuresFutureMap.remove(transactionId); - } - - - @Override - public int getBuffers() { - return buffers; - } - - - @Override - public int getActions() { - return actions; - } - - - @Override - public int getCapabilities() { - return capabilities; - } - - - @Override - public byte getTables() { - return tables; - } - - @Override - public OFDescriptionStatistics getDescriptionStatistics() { - return new OFDescriptionStatistics(description); - } - - - @Override - public void setFloodlightProvider(Controller controller) { - floodlightProvider = controller; - } - - - /** - * For switch drivers to set thresholds, all rates in per second - * @param pktInHigh - above this start throttling - * @param pktInLow - below this stop throttling - * @param pktInPerMac - block host if unique pktIn rate reaches this - * @param pktInPerPort - block port if unique pktIn rate reaches this - */ - @JsonIgnore - protected void setInputThrottleThresholds(int pktInHigh, int pktInLow, - int pktInPerMac, int pktInPerPort) { - packetInRateThresholdHigh = pktInHigh; - packetInRateThresholdLow = pktInLow; - packetInRatePerMacThreshold = pktInPerMac; - packetInRatePerPortThreshold = pktInPerPort; - } - - /** - * Return if switch has exceeded the high threshold of packet in rate. - * @return - */ - @Override - public boolean isOverloaded() { - return packetInThrottleEnabled; - } - - /** - * Determine if this message should be dropped. - * - * We compute the current rate by taking a timestamp every 100 messages. - * Could change to a more complex scheme if more accuracy is needed. - * - * Enable throttling if the rate goes above packetInRateThresholdHigh - * Disable throttling when the rate drops below packetInRateThresholdLow - * - * While throttling is enabled, we do the following: - * - Remove duplicate packetIn's mapped to the same OFMatch - * - After filtering, if packetIn rate per host (mac) is above - * packetInRatePerMacThreshold, push a flow mod to block mac on port - * - After filtering, if packetIn rate per port is above - * packetInRatePerPortThreshold, push a flow mod to block port - * - Allow blocking flow mods have a hard timeout and expires automatically - * - * TODO: keep a history of all events related in input throttling - * - * @param ofm - * @return - */ - @Override - public boolean inputThrottled(OFMessage ofm) { - if (ofm.getType() != OFType.PACKET_IN) { - return false; - } - ctrSwitchPktin.updateCounterNoFlush(); - // Compute current packet in rate - messageCount++; - if (messageCount % 1000 == 0) { - long now = System.currentTimeMillis(); - if (now != lastMessageTime) { - currentRate = (int) (1000000 / (now - lastMessageTime)); - lastMessageTime = now; - } else { - currentRate = Integer.MAX_VALUE; - } - } - if (!packetInThrottleEnabled) { - if (currentRate <= packetInRateThresholdHigh) { - return false; // most common case - } - enablePacketInThrottle(); - } else if (currentRate < packetInRateThresholdLow) { - disablePacketInThrottle(); - return false; - } - - // Now we are in the slow path where we need to do filtering - // First filter based on OFMatch - OFPacketIn pin = (OFPacketIn)ofm; - OFMatch match = new OFMatch(); - match.loadFromPacket(pin.getPacketData(), pin.getInPort()); - if (ofMatchCache.update(match)) { - ctrSwitchPktinDrops.updateCounterNoFlush(); - return true; - } - - // We have packet in with a distinct flow, check per mac rate - messageCountUniqueOFMatch++; - if ((messageCountUniqueOFMatch % packetInRatePerMacThreshold) == 1) { - checkPerSourceMacRate(pin); - } - - // Check per port rate - if ((messageCountUniqueOFMatch % packetInRatePerPortThreshold) == 1) { - checkPerPortRate(pin); - } - return false; - } - - /** - * We rely on the fact that packet in processing is single threaded - * per packet-in, so no locking is necessary. - */ - private void disablePacketInThrottle() { - ofMatchCache = null; - macCache = null; - macBlockedCache = null; - portCache = null; - portBlockedCache = null; - packetInThrottleEnabled = false; - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_OVERLOAD_THROTTLE_DISABLED ==>" + - "Pktin rate " + currentRate + "/s", false); - log.info("Packet in rate is {}, disable throttling on {}", - currentRate, this); - } - - private void enablePacketInThrottle() { - ofMatchCache = new TimedCache<OFMatch>(2048, 5000); // 5 second interval - macCache = new TimedCache<Long>(64, 1000 ); // remember last second - macBlockedCache = new TimedCache<Long>(256, 5000 ); // 5 second interval - portCache = new TimedCache<Short>(16, 1000 ); // rememeber last second - portBlockedCache = new TimedCache<Short>(64, 5000 ); // 5 second interval - packetInThrottleEnabled = true; - messageCountUniqueOFMatch = 0; - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_OVERLOAD_THROTTLE_ENABLED ==>" + - "Pktin rate " + currentRate + "/s", false); - log.info("Packet in rate is {}, enable throttling on {}", - currentRate, this); - } - - private void registerOverloadCounters() throws CounterException { - if (debugCountersRegistered) { - return; - } - if (debugCounters == null) { - log.error("Debug Counter Service not found"); - debugCounters = new NullDebugCounter(); - debugCountersRegistered = true; - } - // every level of the hierarchical counter has to be registered - // even if they are not used - ctrSwitch = debugCounters.registerCounter( - PACKAGE , stringId, - "Counter for this switch", - CounterType.ALWAYS_COUNT); - ctrSwitchPktin = debugCounters.registerCounter( - PACKAGE, stringId + "/pktin", - "Packet in counter for this switch", - CounterType.ALWAYS_COUNT); - ctrSwitchWrite = debugCounters.registerCounter( - PACKAGE, stringId + "/write", - "Write counter for this switch", - CounterType.ALWAYS_COUNT); - ctrSwitchPktinDrops = debugCounters.registerCounter( - PACKAGE, stringId + "/pktin/drops", - "Packet in throttle drop count", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - ctrSwitchWriteDrops = debugCounters.registerCounter( - PACKAGE, stringId + "/write/drops", - "Switch write throttle drop count", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - } - - /** - * Check if we have sampled this mac in the last second. - * Since we check every packetInRatePerMacThreshold packets, - * the presence of the mac in the macCache means the rate is - * above the threshold in a statistical sense. - * - * Take care not to block topology probing packets. Also don't - * push blocking flow mod if we have already done so within the - * last 5 seconds. - * - * @param pin - * @return - */ - private void checkPerSourceMacRate(OFPacketIn pin) { - byte[] data = pin.getPacketData(); - byte[] mac = Arrays.copyOfRange(data, 6, 12); - MACAddress srcMac = MACAddress.valueOf(mac); - short ethType = (short) (((data[12] & 0xff) << 8) + (data[13] & 0xff)); - if (ethType != Ethernet.TYPE_LLDP && ethType != Ethernet.TYPE_BSN && - macCache.update(srcMac.toLong())) { - // Check if we already pushed a flow in the last 5 seconds - if (macBlockedCache.update(srcMac.toLong())) { - return; - } - // write out drop flow per srcMac - int port = pin.getInPort(); - SwitchPort swPort = new SwitchPort(getId(), port); - ForwardingBase.blockHost(floodlightProvider, - swPort, srcMac.toLong(), (short) 5, - AppCookie.makeCookie(OFSWITCH_APP_ID, 0)); - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_PORT_BLOCKED_TEMPORARILY " + - "OFPort " + port + " mac " + srcMac, false); - log.info("Excessive packet in from {} on {}, block host for 5 sec", - srcMac.toString(), swPort); - } - } - - /** - * Works in a similar way as checkPerSourceMacRate(). - * - * TODO Don't block ports with links? - * - * @param pin - * @return - */ - private void checkPerPortRate(OFPacketIn pin) { - Short port = pin.getInPort(); - if (portCache.update(port)) { - // Check if we already pushed a flow in the last 5 seconds - if (portBlockedCache.update(port)) { - return; - } - // write out drop flow per port - SwitchPort swPort = new SwitchPort(getId(), port); - ForwardingBase.blockHost(floodlightProvider, - swPort, -1L, (short) 5, - AppCookie.makeCookie(OFSWITCH_APP_ID, 1)); - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_PORT_BLOCKED_TEMPORARILY " + - "OFPort " + port, false); - log.info("Excessive packet in from {}, block port for 5 sec", - swPort); - } - } - - @Override - @JsonIgnore - @LogMessageDoc(level="WARN", - message="Switch {switch} flow table is full", - explanation="The controller received flow table full " + - "message from the switch, could be caused by increased " + - "traffic pattern", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) - public void setTableFull(boolean isFull) { - if (isFull && !flowTableFull) { - floodlightProvider.addSwitchEvent(this.datapathId, - "SWITCH_FLOW_TABLE_FULL " + - "Table full error from switch", false); - log.warn("Switch {} flow table is full", stringId); - } - flowTableFull = isFull; - } - - - @Override - public short getAccessFlowPriority() { - return accessFlowPriority; - } - - - @Override - public short getCoreFlowPriority() { - return coreFlowPriority; - } - - - @Override - public void setAccessFlowPriority(short accessFlowPriority) { - this.accessFlowPriority = accessFlowPriority; - } - - - @Override - public void setCoreFlowPriority(short coreFlowPriority) { - this.coreFlowPriority = coreFlowPriority; - } - - @Override - public void startDriverHandshake() { - if (startDriverHandshakeCalled) - throw new SwitchDriverSubHandshakeAlreadyStarted(); - startDriverHandshakeCalled = true; - } - - @Override - public boolean isDriverHandshakeComplete() { - if (!startDriverHandshakeCalled) - throw new SwitchDriverSubHandshakeNotStarted(); - return true; - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - if (startDriverHandshakeCalled) - throw new SwitchDriverSubHandshakeCompleted(m); - else - throw new SwitchDriverSubHandshakeNotStarted(); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/PortChangeEvent.java b/src/main/java/net/floodlightcontroller/core/PortChangeEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..cca90d3a35d8c1988c00f69282be51e8d123d65c --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/PortChangeEvent.java @@ -0,0 +1,54 @@ +package net.floodlightcontroller.core; + +import org.projectfloodlight.openflow.protocol.OFPortDesc; + + +/** + * Describes a change of an open flow port + */ +public class PortChangeEvent { + public final OFPortDesc port; + public final PortChangeType type; + /** + * @param port + * @param type + */ + public PortChangeEvent(OFPortDesc port, + PortChangeType type) { + this.port = port; + this.type = type; + } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((port == null) ? 0 : port.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + PortChangeEvent other = (PortChangeEvent) obj; + if (port == null) { + if (other.port != null) return false; + } else if (!port.equals(other.port)) return false; + if (type != other.type) return false; + return true; + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "[" + type + " " + String.format("%s (%d)", port.getName(), port.getPortNo()) + "]"; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/PortChangeType.java b/src/main/java/net/floodlightcontroller/core/PortChangeType.java new file mode 100644 index 0000000000000000000000000000000000000000..178d27b7603eebaa1c8400160843fd4e5d04be33 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/PortChangeType.java @@ -0,0 +1,8 @@ +package net.floodlightcontroller.core; + +/** + * the type of change that happened to an open flow port + */ +public enum PortChangeType { + ADD, OTHER_UPDATE, DELETE, UP, DOWN, +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/RoleInfo.java b/src/main/java/net/floodlightcontroller/core/RoleInfo.java index 1e6c186f759e2d7b81b529f91438d3b37210f46e..31ec6464c95932a094717a02b18f400d98764d8f 100644 --- a/src/main/java/net/floodlightcontroller/core/RoleInfo.java +++ b/src/main/java/net/floodlightcontroller/core/RoleInfo.java @@ -16,67 +16,34 @@ package net.floodlightcontroller.core; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.TimeZone; - -import net.floodlightcontroller.core.IFloodlightProviderService.Role; import com.fasterxml.jackson.annotation.JsonProperty; public class RoleInfo { - protected String role; - protected String roleChangeDescription; - protected Date roleChangeDateTime; - - public RoleInfo() { - } - - public RoleInfo(RoleInfo o) { - role = o.role; - roleChangeDescription = o.roleChangeDescription; - roleChangeDateTime = (Date)o.roleChangeDateTime.clone(); - } + private final HARole role; + private final String roleChangeDescription; + private final Date roleChangeDateTime; - public RoleInfo(String role) { - setRole(role); - } - - public RoleInfo(Role role, String description) { - this.role = (role != null) ? role.name() : "DISABLED"; - this.roleChangeDescription = description; - } - - public RoleInfo(Role role, String description, Date dt) { - this.role = (role != null) ? role.name() : "DISABLED"; + public RoleInfo(HARole role, String description, Date dt) { + this.role = role; this.roleChangeDescription = description; this.roleChangeDateTime = dt; } - public String getRole() { + public HARole getRole() { return role; } - public void setRole(String role) { - this.role = role; - } - @JsonProperty(value="change-description") public String getRoleChangeDescription() { return roleChangeDescription; } - @JsonProperty(value="change-description") - public void setRoleChangeDescription(String roleChangeDescription) { - this.roleChangeDescription = roleChangeDescription; - } + @JsonProperty(value="change-date-time") - public String getRoleChangeDateTime() { - SimpleDateFormat formatter = - new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - formatter.setTimeZone(TimeZone.getTimeZone("UTC")); - return roleChangeDateTime == null ? - "" : formatter.format(roleChangeDateTime); + public Date getRoleChangeDateTime() { + return roleChangeDateTime; } -} \ No newline at end of file +} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDescription.java b/src/main/java/net/floodlightcontroller/core/SwitchDescription.java new file mode 100644 index 0000000000000000000000000000000000000000..57697d70916554da6cb73881b1237fadcd863101 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/SwitchDescription.java @@ -0,0 +1,182 @@ +package net.floodlightcontroller.core; + +import org.projectfloodlight.openflow.protocol.OFDescStatsReply; + +/** + * Encapsulates the switch information return from the description stats request + * + * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com> + */ +public class SwitchDescription { + + public static class Builder { + + private String manufacturerDescription; + private String hardwareDescription; + private String softwareDescription; + private String serialNumber; + private String datapathDescription; + + public Builder() { + manufacturerDescription = ""; + hardwareDescription = ""; + softwareDescription = ""; + serialNumber = ""; + datapathDescription = ""; + } + + public Builder setManufacturerDescription(String manufacturerDescription) { + this.manufacturerDescription = manufacturerDescription; + return this; + } + + public Builder setHardwareDescription(String hardwareDescription) { + this.hardwareDescription = hardwareDescription; + return this; + } + + public Builder setSoftwareDescription(String softwareDescription) { + this.softwareDescription = softwareDescription; + return this; + } + + public Builder setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + return this; + } + + public Builder setDatapathDescription(String datapathDescription) { + this.datapathDescription = datapathDescription; + return this; + } + + public SwitchDescription build() { + return new SwitchDescription(manufacturerDescription, + hardwareDescription, softwareDescription, serialNumber, + datapathDescription); + } + } + + private final String manufacturerDescription; + private final String hardwareDescription; + private final String softwareDescription; + private final String serialNumber; + private final String datapathDescription; + + public static Builder builder() { + return new Builder(); + } + + // FIXME: Should make this private + public SwitchDescription() { + this("", "", "", "", ""); + } + + // FIXME: Should make this private + public SwitchDescription(String manufacturerDescription, + String hardwareDescription, String softwareDescription, + String serialNumber, String datapathDescription) { + this.manufacturerDescription = manufacturerDescription; + this.hardwareDescription = hardwareDescription; + this.softwareDescription = softwareDescription; + this.serialNumber = serialNumber; + this.datapathDescription = datapathDescription; + } + + public SwitchDescription(OFDescStatsReply descStatsReply) { + this(descStatsReply.getMfrDesc(), descStatsReply.getHwDesc(), + descStatsReply.getSwDesc(), descStatsReply.getSerialNum(), + descStatsReply.getDpDesc()); + } + + public String getManufacturerDescription() { + return manufacturerDescription; + } + + public String getHardwareDescription() { + return hardwareDescription; + } + + public String getSoftwareDescription() { + return softwareDescription; + } + + public String getSerialNumber() { + return serialNumber; + } + + public String getDatapathDescription() { + return datapathDescription; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime + * result + + ((datapathDescription == null) ? 0 : datapathDescription + .hashCode()); + result = prime + * result + + ((hardwareDescription == null) ? 0 : hardwareDescription + .hashCode()); + result = prime + * result + + ((manufacturerDescription == null) ? 0 + : manufacturerDescription.hashCode()); + result = prime * result + + ((serialNumber == null) ? 0 : serialNumber.hashCode()); + result = prime + * result + + ((softwareDescription == null) ? 0 : softwareDescription + .hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SwitchDescription other = (SwitchDescription) obj; + if (datapathDescription == null) { + if (other.datapathDescription != null) + return false; + } else if (!datapathDescription.equals(other.datapathDescription)) + return false; + if (hardwareDescription == null) { + if (other.hardwareDescription != null) + return false; + } else if (!hardwareDescription.equals(other.hardwareDescription)) + return false; + if (manufacturerDescription == null) { + if (other.manufacturerDescription != null) + return false; + } else if (!manufacturerDescription + .equals(other.manufacturerDescription)) + return false; + if (serialNumber == null) { + if (other.serialNumber != null) + return false; + } else if (!serialNumber.equals(other.serialNumber)) + return false; + if (softwareDescription == null) { + if (other.softwareDescription != null) + return false; + } else if (!softwareDescription.equals(other.softwareDescription)) + return false; + return true; + } + + @Override + public String toString() { + return "SwitchDescription [manufacturerDescription=" + manufacturerDescription + + ", hardwareDescription=" + hardwareDescription + ", softwareDescription=" + + softwareDescription + ", serialNumber=" + serialNumber + + ", datapathDescription=" + datapathDescription + "]"; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java b/src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java new file mode 100644 index 0000000000000000000000000000000000000000..21b74ec7470071ee2fee36333c0316fd3381b5d7 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java @@ -0,0 +1,23 @@ +package net.floodlightcontroller.core; + +import org.projectfloodlight.openflow.types.DatapathId; + +public class SwitchDisconnectedException extends Exception { + private static final long serialVersionUID = 1L; + + private final DatapathId id; + + public SwitchDisconnectedException(DatapathId id) { + super(genMessage(id)); + this.id = id; + } + + private static String genMessage(DatapathId id) { + return String.format("Switch %s disconnected", id); + } + + public DatapathId getId() { + return id; + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java deleted file mode 100644 index eb5541bf960694a1961882c24bf79e2536b41644..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.floodlightcontroller.core; - -/** - * Thrown when IOFSwitch.startDriverHandshake() is called more than once. - * @author gregor - * - */ -public class SwitchDriverSubHandshakeAlreadyStarted extends - SwitchDriverSubHandshakeException { - private static final long serialVersionUID = -5491845708752443501L; - - public SwitchDriverSubHandshakeAlreadyStarted() { - super(); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java deleted file mode 100644 index ed39b5f44bc34597b41d3fc848d2b3410c7943b4..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.floodlightcontroller.core; - -import org.openflow.protocol.OFMessage; - -/** - * Indicates that a message was passed to a switch driver's subhandshake - * handling code but the driver has already completed the sub-handshake - * @author gregor - * - */ -public class SwitchDriverSubHandshakeCompleted - extends SwitchDriverSubHandshakeException { - private static final long serialVersionUID = -8817822245846375995L; - - public SwitchDriverSubHandshakeCompleted(OFMessage m) { - super("Sub-Handshake is already complete but received message " + - m.getType()); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java deleted file mode 100644 index 0c0c87390468b304db6865c04a228d7e351a73dc..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.floodlightcontroller.core; - -/** - * Base class for exception thrown by switch driver sub-handshake processing - * @author gregor - * - */ -public class SwitchDriverSubHandshakeException extends RuntimeException { - private static final long serialVersionUID = -6257836781419604438L; - - protected SwitchDriverSubHandshakeException() { - super(); - } - - protected SwitchDriverSubHandshakeException(String arg0, Throwable arg1) { - super(arg0, arg1); - } - - protected SwitchDriverSubHandshakeException(String arg0) { - super(arg0); - } - - protected SwitchDriverSubHandshakeException(Throwable arg0) { - super(arg0); - } - -} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java deleted file mode 100644 index 67ec68be2c1540f56db63632a0e82757cb92a719..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.floodlightcontroller.core; - -/** - * Thrown when a switch driver's sub-handshake has not been started but an - * operation requiring the sub-handshake has been attempted. - * @author gregor - * - */ -public class SwitchDriverSubHandshakeNotStarted extends - SwitchDriverSubHandshakeException { - private static final long serialVersionUID = -5491845708752443501L; - - public SwitchDriverSubHandshakeNotStarted() { - super(); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java deleted file mode 100644 index 1f49aea7ab60c9a58d77f7753f617b25015e4346..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.floodlightcontroller.core; - -/** - * Thrown when a switch driver's sub-handshake state-machine receives an - * unexpected OFMessage and/or is in an invald state - * @author gregor - * - */ -public class SwitchDriverSubHandshakeStateException extends - SwitchDriverSubHandshakeException { - private static final long serialVersionUID = -8249926069195147051L; - - public SwitchDriverSubHandshakeStateException(String msg) { - super(msg); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java b/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java index 6284ba3c38785c2e5dc21421d012147f74c165ed..ea583510844a32655d7019afe2a10d620a02c892 100644 --- a/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java +++ b/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java @@ -2,16 +2,20 @@ package net.floodlightcontroller.core; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Set; -import net.floodlightcontroller.util.EnumBitmaps; -import net.floodlightcontroller.util.MACAddress; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFPortDesc; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFPhysicalPort; -import org.openflow.protocol.OFPhysicalPort.OFPortState; -import org.openflow.protocol.statistics.OFDescriptionStatistics; -import org.openflow.util.HexString; +import net.floodlightcontroller.core.SwitchDescription; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFCapabilities; +import org.projectfloodlight.openflow.protocol.OFActionType; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -27,27 +31,11 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class SwitchSyncRepresentation { public static class SyncedPort { @JsonProperty - public short portNumber; - @JsonProperty - public long hardwareAddress; - @JsonProperty - public String name; - @JsonProperty - public int config; - @JsonProperty - public int state; - @JsonProperty - public int currentFeatures; - @JsonProperty - public int advertisedFeatures; - @JsonProperty - public int supportedFeatures; - @JsonProperty - public int peerFeatures; + public OFPortDesc port; - public static SyncedPort fromImmutablePort(ImmutablePort p) { + /*public static SyncedPort fromImmutablePort(OFPortDesc p) { SyncedPort rv = new SyncedPort(); - rv.portNumber = p.getPortNumber(); + rv.port = OFPortDesc.of(p.getPortNumber()); if (p.getHardwareAddress() == null) { rv.hardwareAddress = 0; } else { @@ -66,32 +54,38 @@ public class SwitchSyncRepresentation { EnumBitmaps.toBitmap(p.getSupportedFeatures()); rv.peerFeatures = EnumBitmaps.toBitmap(p.getPeerFeatures()); return rv; - } - - public OFPhysicalPort toOFPhysicalPort() { - OFPhysicalPort p = new OFPhysicalPort(); - p.setPortNumber(portNumber); - p.setHardwareAddress(MACAddress.valueOf(hardwareAddress).toBytes()); - p.setName(name); - p.setConfig(config); - p.setState(state); - p.setCurrentFeatures(currentFeatures); - p.setAdvertisedFeatures(advertisedFeatures); - p.setSupportedFeatures(supportedFeatures); - p.setPeerFeatures(peerFeatures); - return p; + }*/ + + public static SyncedPort fromOFPortDesc(OFPortDesc ofpd) { + SyncedPort sp = new SyncedPort(); + sp.port = ofpd; + return sp; + } + + public OFPortDesc toOFPortDesc(OFFactory factory) { + OFPortDesc.Builder builder = factory.buildPortDesc(); + builder.setPortNo(port.getPortNo()); + builder.setHwAddr(port.getHwAddr()); + builder.setName(port.getName()); + builder.setConfig(port.getConfig()); + builder.setState(port.getState()); + builder.setCurr(port.getCurr()); + builder.setAdvertised(port.getAdvertised()); + builder.setSupported(port.getSupported()); + builder.setPeer(port.getPeer()); + return builder.build(); } } // From FeaturesReply - private final long dpid; - private final int buffers; - private final byte tables; - private final int capabilities; - private final int actions; + private final DatapathId dpid; + private final long buffers; + private final short tables; + private final Set<OFCapabilities> capabilities; + private final Set<OFActionType> actions; private final List<SyncedPort> ports; - // From OFDescriptionStatistics + // From OFDescStatsReply private final String manufacturerDescription; private final String hardwareDescription; private final String softwareDescription; @@ -115,11 +109,11 @@ public class SwitchSyncRepresentation { */ @JsonCreator public SwitchSyncRepresentation( - @JsonProperty("dpid") long dpid, + @JsonProperty("dpid") DatapathId dpid, @JsonProperty("buffers") int buffers, @JsonProperty("tables") byte tables, - @JsonProperty("capabilities") int capabilities, - @JsonProperty("actions") int actions, + @JsonProperty("capabilities") Set<OFCapabilities> capabilities, + @JsonProperty("actions") Set<OFActionType> actions, @JsonProperty("ports") List<SyncedPort> ports, @JsonProperty("manufacturerDescription") String manufacturerDescription, @JsonProperty("hardwareDescription") String hardwareDescription, @@ -147,7 +141,7 @@ public class SwitchSyncRepresentation { this.actions = sw.getActions(); this.ports = toSyncedPortList(sw.getPorts()); - OFDescriptionStatistics d = sw.getDescriptionStatistics(); + SwitchDescription d = sw.getSwitchDescription(); this.manufacturerDescription = d.getManufacturerDescription(); this.hardwareDescription = d.getHardwareDescription(); this.softwareDescription = d.getSoftwareDescription(); @@ -156,14 +150,13 @@ public class SwitchSyncRepresentation { } public SwitchSyncRepresentation(OFFeaturesReply fr, - OFDescriptionStatistics d) { + SwitchDescription d) { this.dpid = fr.getDatapathId(); - this.buffers = fr.getBuffers(); - this.tables = fr.getTables(); + this.buffers = fr.getNBuffers(); + this.tables = fr.getNTables(); this.capabilities = fr.getCapabilities(); this.actions = fr.getActions(); - this.ports = toSyncedPortList( - ImmutablePort.immutablePortListOf(fr.getPorts())); + this.ports = toSyncedPortList(fr.getPorts()); this.manufacturerDescription = d.getManufacturerDescription(); this.hardwareDescription = d.getHardwareDescription(); @@ -172,65 +165,73 @@ public class SwitchSyncRepresentation { this.datapathDescription = d.getDatapathDescription(); } - private static List<SyncedPort> toSyncedPortList(Collection<ImmutablePort> ports) { + private static List<SyncedPort> toSyncedPortList(Collection<OFPortDesc> ports) { List<SyncedPort> rv = new ArrayList<SyncedPort>(ports.size()); - for (ImmutablePort p: ports) { - rv.add(SyncedPort.fromImmutablePort(p)); + for (OFPortDesc p: ports) { + rv.add(SyncedPort.fromOFPortDesc(p)); } return rv; } - private static List<OFPhysicalPort> toOFPhysicalPortList(Collection<SyncedPort> ports) { - List<OFPhysicalPort> rv = new ArrayList<OFPhysicalPort>(ports.size()); + private static List<OFPortDesc> toOFPortDescList(OFFactory factory, Collection<SyncedPort> ports) { + List<OFPortDesc> rv = new ArrayList<OFPortDesc>(ports.size()); for (SyncedPort p: ports) { - rv.add(p.toOFPhysicalPort()); + rv.add(p.toOFPortDesc(factory)); } return rv; } @JsonIgnore - public OFFeaturesReply getFeaturesReply() { - OFFeaturesReply fr = new OFFeaturesReply(); - fr.setDatapathId(dpid); - fr.setBuffers(buffers); - fr.setTables(tables); - fr.setCapabilities(capabilities); - fr.setActions(actions); - fr.setPorts(toOFPhysicalPortList(ports)); - return fr; + public OFFeaturesReply getFeaturesReply(OFFactory factory) { + /** + * FIXME Icky work around; if a null actions got written to storage + * then fake up an empty one so the builder() doesn't throw + * a NPE. Need to root cause why someone would write a null actions. + * This code will all be removed shortly -- needed to unblock BVS team. + */ + Set<OFActionType> workAroundActions; + if (actions != null) + workAroundActions = actions; + else + workAroundActions = Collections.<OFActionType> emptySet(); + + OFFeaturesReply featuresReply = factory.buildFeaturesReply() + .setXid(0) + .setDatapathId(dpid) + .setNBuffers(buffers) + .setNTables(tables) + .setCapabilities(capabilities) + .setActions(workAroundActions) + .setPorts(toOFPortDescList(factory, ports)) + .build(); + return featuresReply; } @JsonIgnore - public OFDescriptionStatistics getDescription() { - OFDescriptionStatistics desc = new OFDescriptionStatistics(); - desc.setManufacturerDescription(manufacturerDescription); - desc.setHardwareDescription(hardwareDescription); - desc.setSoftwareDescription(softwareDescription); - desc.setSerialNumber(serialNumber); - desc.setDatapathDescription(datapathDescription); - return desc; + public SwitchDescription getDescription() { + return new SwitchDescription(manufacturerDescription, + hardwareDescription, softwareDescription, softwareDescription, + datapathDescription); } - - - public long getDpid() { + public DatapathId getDpid() { return dpid; } - public int getBuffers() { + public long getBuffers() { return buffers; } - public byte getTables() { + public short getTables() { return tables; } - public int getCapabilities() { + public Set<OFCapabilities> getCapabilities() { return capabilities; } - public int getActions() { + public Set<OFActionType> getActions() { return actions; } @@ -261,7 +262,7 @@ public class SwitchSyncRepresentation { @Override public String toString() { String dpidString; - dpidString = HexString.toHexString(dpid); + dpidString = HexString.toHexString(dpid.getLong()); return "SwitchSyncRepresentation [DPID=" + dpidString + "]"; } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java deleted file mode 100644 index 7d6227d108b6a1279056b450622c05750f77e90c..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ /dev/null @@ -1,2696 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import java.io.FileInputStream; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Set; -import java.util.Stack; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.HAListenerTypeMarker; -import net.floodlightcontroller.core.IFloodlightProviderService; -import net.floodlightcontroller.core.IHAListener; -import net.floodlightcontroller.core.IInfoProvider; -import net.floodlightcontroller.core.IListener.Command; -import net.floodlightcontroller.core.IOFMessageListener; -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.IOFSwitch.PortChangeEvent; -import net.floodlightcontroller.core.IOFSwitch.PortChangeType; -import net.floodlightcontroller.core.IOFSwitchDriver; -import net.floodlightcontroller.core.IOFSwitchListener; -import net.floodlightcontroller.core.IReadyForReconcileListener; -import net.floodlightcontroller.core.ImmutablePort; -import net.floodlightcontroller.core.OFSwitchBase; -import net.floodlightcontroller.core.RoleInfo; -import net.floodlightcontroller.core.SwitchSyncRepresentation; -import net.floodlightcontroller.core.annotations.LogMessageDoc; -import net.floodlightcontroller.core.annotations.LogMessageDocs; -import net.floodlightcontroller.core.module.FloodlightModuleException; -import net.floodlightcontroller.core.util.ListenerDispatcher; -import net.floodlightcontroller.core.web.CoreWebRoutable; -import net.floodlightcontroller.counter.ICounterStoreService; -import net.floodlightcontroller.debugcounter.IDebugCounter; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException; -import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType; -import net.floodlightcontroller.debugevent.IDebugEventService; -import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; -import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType; -import net.floodlightcontroller.debugevent.IEventUpdater; -import net.floodlightcontroller.debugevent.NullDebugEvent; -import net.floodlightcontroller.debugevent.IDebugEventService.EventType; -import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered; -import net.floodlightcontroller.notification.INotificationManager; -import net.floodlightcontroller.notification.NotificationManagerFactory; -import net.floodlightcontroller.packet.Ethernet; -import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; -import net.floodlightcontroller.restserver.IRestApiService; -import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.IStorageSourceListener; -import net.floodlightcontroller.storage.IStorageSourceService; -import net.floodlightcontroller.storage.StorageException; -import net.floodlightcontroller.threadpool.IThreadPoolService; -import net.floodlightcontroller.util.LoadMonitor; -import net.floodlightcontroller.util.TimedCache; - -import org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.group.ChannelGroup; -import org.jboss.netty.channel.group.DefaultChannelGroup; -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFType; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.statistics.OFDescriptionStatistics; -import org.openflow.util.HexString; -import org.openflow.vendor.nicira.OFNiciraVendorExtensions; -import org.sdnplatform.sync.IClosableIterator; -import org.sdnplatform.sync.IStoreClient; -import org.sdnplatform.sync.IStoreListener; -import org.sdnplatform.sync.ISyncService; -import org.sdnplatform.sync.ISyncService.Scope; -import org.sdnplatform.sync.Versioned; -import org.sdnplatform.sync.error.ObsoleteVersionException; -import org.sdnplatform.sync.error.SyncException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.bigswitch.floodlight.vendor.OFVendorActions; - - - -/** - * The main controller class. Handles all setup and network listeners - */ -public class Controller implements IFloodlightProviderService, - IStorageSourceListener, IInfoProvider { - - protected static final Logger log = LoggerFactory.getLogger(Controller.class); - protected static final INotificationManager notifier = - NotificationManagerFactory.getNotificationManager(Controller.class); - - static final String ERROR_DATABASE = - "The controller could not communicate with the system database."; - static final String SWITCH_SYNC_STORE_NAME = - Controller.class.getCanonicalName() + ".stateStore"; - - protected BasicFactory factory; - protected ConcurrentMap<OFType, - ListenerDispatcher<OFType,IOFMessageListener>> - messageListeners; - - // OFSwitch driver binding map and order - private ISwitchDriverRegistry driverRegistry; - - // The controllerNodeIPsCache maps Controller IDs to their IP address. - // It's only used by handleControllerNodeIPsChanged - protected HashMap<String, String> controllerNodeIPsCache; - - protected Set<IOFSwitchListener> switchListeners; - protected ListenerDispatcher<HAListenerTypeMarker,IHAListener> haListeners; - protected Set<IReadyForReconcileListener> readyForReconcileListeners; - protected Map<String, List<IInfoProvider>> providerMap; - protected BlockingQueue<IUpdate> updates; - - // Module dependencies - private IRestApiService restApi; - private ICounterStoreService counterStore = null; - private IDebugCounterService debugCounters; - protected IDebugEventService debugEvents; - private IStorageSourceService storageSource; - private IPktInProcessingTimeService pktinProcTime; - private IThreadPoolService threadPool; - private ScheduledExecutorService ses; - private ISyncService syncService; - private IStoreClient<Long, SwitchSyncRepresentation> storeClient; - - // Configuration options - protected String openFlowHost = null; - protected int openFlowPort = 6633; - protected int workerThreads = 0; - - - // This controller's current role that modules can use/query to decide - // if they should operate in master or slave mode. - // TODO: potentially we need to get rid of this field and modules must - // then rely on the role notifications alone... - protected volatile Role notifiedRole; - - private static final String - INITIAL_ROLE_CHANGE_DESCRIPTION = "Controller startup."; - private RoleManager roleManager; - private SwitchManager switchManager; - - private static final int DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS = - 15*1000; // 15s - private int consolidateStoreTimeDelayMs = - DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS; - - - // Flag to always flush flow table on switch reconnect (HA or otherwise) - private boolean alwaysClearFlowsOnSwActivate = false; - private TimedCache<Long> swConnectCache; - - // Storage table names - protected static final String CONTROLLER_TABLE_NAME = "controller_controller"; - protected static final String CONTROLLER_ID = "id"; - - protected static final String SWITCH_CONFIG_TABLE_NAME = "controller_switchconfig"; - protected static final String SWITCH_CONFIG_CORE_SWITCH = "core_switch"; - - protected static final String CONTROLLER_INTERFACE_TABLE_NAME = "controller_controllerinterface"; - protected static final String CONTROLLER_INTERFACE_ID = "id"; - protected static final String CONTROLLER_INTERFACE_CONTROLLER_ID = "controller_id"; - protected static final String CONTROLLER_INTERFACE_TYPE = "type"; - protected static final String CONTROLLER_INTERFACE_NUMBER = "number"; - protected static final String CONTROLLER_INTERFACE_DISCOVERED_IP = "discovered_ip"; - - // FIXME: don't use "forwardingconfig" as table name - private static final String FLOW_PRIORITY_TABLE_NAME = "controller_forwardingconfig"; - private static final String FLOW_COLUMN_PRIMARY_KEY = "id"; - private static final String FLOW_VALUE_PRIMARY_KEY = "forwarding"; - private static final String FLOW_COLUMN_ACCESS_PRIORITY = "access_priority"; - private static final String FLOW_COLUMN_CORE_PRIORITY = "core_priority"; - private static final String[] FLOW_COLUMN_NAMES = new String[] { - FLOW_COLUMN_PRIMARY_KEY, - FLOW_COLUMN_ACCESS_PRIORITY, - FLOW_COLUMN_CORE_PRIORITY - }; - - private static final short DEFAULT_ACCESS_PRIORITY = 10; - private static final short DEFAULT_CORE_PRIORITY = 1000; - private short accessPriority = DEFAULT_ACCESS_PRIORITY; - private short corePriority = DEFAULT_CORE_PRIORITY; - - - // Perf. related configuration - protected static final int SEND_BUFFER_SIZE = 128 * 1024; - public static final int BATCH_MAX_SIZE = 100; - protected static final boolean ALWAYS_DECODE_ETH = true; - - // Set of port name prefixes that will be classified as uplink ports, - // hence will not be autoportfast. - Set<String> uplinkPortPrefixSet; - - @Override - public Set<String> getUplinkPortPrefixSet() { - return uplinkPortPrefixSet; - } - - public void setUplinkPortPrefixSet(Set<String> prefixSet) { - this.uplinkPortPrefixSet = prefixSet; - } - - // Event IDs for debug events - protected IEventUpdater<SwitchEvent> evSwitch; - - // Load monitor for overload protection - protected final boolean overload_drop = - Boolean.parseBoolean(System.getProperty("overload_drop", "false")); - protected final LoadMonitor loadmonitor = new LoadMonitor(log); - - private class NotificationSwitchListener implements IOFSwitchListener { - - @Override - public void switchAdded(long switchId) { - notifier.postNotification("Switch " + HexString.toHexString(switchId) + " connected."); - } - - @Override - public void switchRemoved(long switchId) { - notifier.postNotification("Switch " + HexString.toHexString(switchId) + " disconnected."); - } - - @Override - public void switchActivated(long switchId) { - } - - @Override - public void switchPortChanged(long switchId, ImmutablePort port, - PortChangeType type) { - String msg = String.format("Switch %s port %s changed: %s", - HexString.toHexString(switchId), - port.getName(), - type.toString()); - notifier.postNotification(msg); - } - - @Override - public void switchChanged(long switchId) { - } - } - public static class Counters { - public static final String prefix = Controller.class.getPackage().getName(); - public IDebugCounter setRoleEqual; - public IDebugCounter setSameRole; - public IDebugCounter setRoleMaster; - public IDebugCounter remoteStoreNotification; - public IDebugCounter invalidPortsChanged; - public IDebugCounter invalidSwitchActivatedWhileSlave; - public IDebugCounter invalidStoreEventWhileMaster; - public IDebugCounter switchDisconnectedWhileSlave; - public IDebugCounter switchActivated; - public IDebugCounter errorSameSwitchReactivated; // err - public IDebugCounter switchWithSameDpidActivated; // warn - public IDebugCounter newSwitchActivated; // new switch - public IDebugCounter syncedSwitchActivated; - public IDebugCounter readyForReconcile; - public IDebugCounter newSwitchFromStore; - public IDebugCounter updatedSwitchFromStore; - public IDebugCounter switchDisconnected; - public IDebugCounter syncedSwitchRemoved; - public IDebugCounter unknownSwitchRemovedFromStore; - public IDebugCounter consolidateStoreRunCount; - public IDebugCounter consolidateStoreInconsistencies; - public IDebugCounter storeSyncError; - public IDebugCounter switchesNotReconnectingToNewMaster; - public IDebugCounter switchPortChanged; - public IDebugCounter switchOtherChange; - public IDebugCounter dispatchMessageWhileSlave; - public IDebugCounter dispatchMessage; // does this cnt make sense? more specific?? per type? count stops? - public IDebugCounter controllerNodeIpsChanged; - public IDebugCounter messageReceived; - public IDebugCounter messageInputThrottled; - public IDebugCounter switchDisconnectReadTimeout; - public IDebugCounter switchDisconnectHandshakeTimeout; - public IDebugCounter switchDisconnectIOError; - public IDebugCounter switchDisconnectParseError; - public IDebugCounter switchDisconnectSwitchStateException; - public IDebugCounter rejectedExecutionException; - public IDebugCounter switchDisconnectOtherException; - public IDebugCounter switchConnected; - public IDebugCounter unhandledMessage; - public IDebugCounter packetInWhileSwitchIsSlave; - public IDebugCounter epermErrorWhileSwitchIsMaster; - public IDebugCounter roleNotResentBecauseRolePending; - public IDebugCounter roleRequestSent; - public IDebugCounter roleReplyTimeout; - public IDebugCounter roleReplyReceived; // expected RoleReply received - public IDebugCounter roleReplyErrorUnsupported; - public IDebugCounter switchCounterRegistrationFailed; - - void createCounters(IDebugCounterService debugCounters) throws CounterException { - setRoleEqual = - debugCounters.registerCounter( - prefix, "set-role-equal", - "Controller received a role request with role of "+ - "EQUAL which is unusual", - CounterType.ALWAYS_COUNT); - setSameRole = - debugCounters.registerCounter( - prefix, "set-same-role", - "Controller received a role request for the same " + - "role the controller already had", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - setRoleMaster = - debugCounters.registerCounter( - prefix, "set-role-master", - "Controller received a role request with role of " + - "MASTER. This counter can be at most 1.", - CounterType.ALWAYS_COUNT); - - remoteStoreNotification = - debugCounters.registerCounter( - prefix, "remote-store-notification", - "Received a notification from the sync service " + - "indicating that switch information has changed", - CounterType.ALWAYS_COUNT); - - invalidPortsChanged = - debugCounters.registerCounter( - prefix, "invalid-ports-changed", - "Received an unexpected ports changed " + - "notification while the controller was in " + - "SLAVE role.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - invalidSwitchActivatedWhileSlave = - debugCounters.registerCounter( - prefix, "invalid-switch-activated-while-slave", - "Received an unexpected switchActivated " + - "notification while the controller was in " + - "SLAVE role.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - invalidStoreEventWhileMaster = - debugCounters.registerCounter( - prefix, "invalid-store-event-while-master", - "Received an unexpected notification from " + - "the sync store while the controller was in " + - "MASTER role.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - switchDisconnectedWhileSlave = - debugCounters.registerCounter( - prefix, "switch-disconnected-while-slave", - "A switch disconnected and the controller was " + - "in SLAVE role.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - switchActivated = - debugCounters.registerCounter( - prefix, "switch-activated", - "A switch connected to this controller is now " + - "in MASTER role", - CounterType.ALWAYS_COUNT); - - errorSameSwitchReactivated = // err - debugCounters.registerCounter( - prefix, "error-same-switch-reactivated", - "A switch that was already in active state " + - "was activated again. This indicates a " + - "controller defect", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - - switchWithSameDpidActivated = // warn - debugCounters.registerCounter( - prefix, "switch-with-same-dpid-activated", - "A switch with the same DPID as another switch " + - "connected to the controller. This can be " + - "caused by multiple switches configured with " + - "the same DPID or by a switch reconnecting very " + - "quickly.", - CounterType.COUNT_ON_DEMAND, - IDebugCounterService.CTR_MDATA_WARN); - - newSwitchActivated = // new switch - debugCounters.registerCounter( - prefix, "new-switch-activated", - "A new switch has completed the handshake as " + - "MASTER. The switch was not known to any other " + - "controller in the cluster", - CounterType.ALWAYS_COUNT); - syncedSwitchActivated = - debugCounters.registerCounter( - prefix, "synced-switch-activated", - "A switch has completed the handshake as " + - "MASTER. The switch was known to another " + - "controller in the cluster", - CounterType.ALWAYS_COUNT); - - readyForReconcile = - debugCounters.registerCounter( - prefix, "ready-for-reconcile", - "Controller is ready for flow reconciliation " + - "after Slave to Master transition. Either all " + - "previously known switches are now active " + - "or they have timed out and have been removed." + - "This counter will be 0 or 1.", - CounterType.ALWAYS_COUNT); - - newSwitchFromStore = - debugCounters.registerCounter( - prefix, "new-switch-from-store", - "A new switch has connected to another " + - "another controller in the cluster. This " + - "controller instance has received a sync store " + - "notification for it.", - CounterType.ALWAYS_COUNT); - - updatedSwitchFromStore = - debugCounters.registerCounter( - prefix, "updated-switch-from-store", - "Information about a switch connected to " + - "another controller instance was updated in " + - "the sync store. This controller instance has " + - "received a notification for it", - CounterType.ALWAYS_COUNT); - - switchDisconnected = - debugCounters.registerCounter( - prefix, "switch-disconnected", - "FIXME: switch has disconnected", - CounterType.ALWAYS_COUNT); - - syncedSwitchRemoved = - debugCounters.registerCounter( - prefix, "synced-switch-removed", - "A switch connected to another controller " + - "instance has disconnected from the controller " + - "cluster. This controller instance has " + - "received a notification for it", - CounterType.ALWAYS_COUNT); - - unknownSwitchRemovedFromStore = - debugCounters.registerCounter( - prefix, "unknown-switch-removed-from-store", - "This controller instances has received a sync " + - "store notification that a switch has " + - "disconnected but this controller instance " + - "did not have the any information about the " + - "switch", // might be less than warning - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - consolidateStoreRunCount = - debugCounters.registerCounter( - prefix, "consolidate-store-run-count", - "This controller has transitioned from SLAVE " + - "to MASTER and waited for switches to reconnect. " + - "The controller has finished waiting and has " + - "reconciled switch entries in the sync store " + - "with live state", - CounterType.ALWAYS_COUNT); - - consolidateStoreInconsistencies = - debugCounters.registerCounter( - prefix, "consolidate-store-inconsistencies", - "During switch sync store consolidation: " + - "Number of switches that were in the store " + - "but not otherwise known plus number of " + - "switches that were in the store previously " + - "but are now missing plus number of " + - "connected switches that were absent from " + - "the store although this controller has " + - "written them. A non-zero count " + - "indicates a brief split-brain dual MASTER " + - "situation during fail-over", - CounterType.ALWAYS_COUNT); - - storeSyncError = - debugCounters.registerCounter( - prefix, "store-sync-error", - "Number of times a sync store operation failed " + - "due to a store sync exception or an entry in " + - "in the store had invalid data.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - - switchesNotReconnectingToNewMaster = - debugCounters.registerCounter( - prefix, "switches-not-reconnecting-to-new-master", - "Switches that were connected to another " + - "controller instance in the cluster but that " + - "did not reconnect to this controller after it " + - "transitioned to MASTER", // might be less than warning - CounterType.ALWAYS_COUNT); - - switchPortChanged = - debugCounters.registerCounter( - prefix, "switch-port-changed", - "Number of times switch ports have changed", - CounterType.ALWAYS_COUNT); - switchOtherChange = - debugCounters.registerCounter( - prefix, "switch-other-change", - "Number of times other information of a switch " + - "has changed.", - CounterType.ALWAYS_COUNT); - - dispatchMessageWhileSlave = - debugCounters.registerCounter( - prefix, "dispatch-message-while-slave", - "Number of times an OF message was received " + - "and supposed to be dispatched but the " + - "controller was in SLAVE role and the message " + - "was not dispatched", - CounterType.ALWAYS_COUNT); - - dispatchMessage = // does this cnt make sense? more specific?? per type? count stops? - debugCounters.registerCounter( - prefix, "dispatch-message", - "Number of times an OF message was dispatched " + - "to registered modules", - CounterType.ALWAYS_COUNT); - - controllerNodeIpsChanged = - debugCounters.registerCounter( - prefix, "controller-nodes-ips-changed", - "IP addresses of controller nodes have changed", - CounterType.ALWAYS_COUNT); - - //------------------------ - // channel handler counters. Factor them out ?? - messageReceived = - debugCounters.registerCounter( - prefix, "message-received", - "Number of OpenFlow messages received. Some of " + - "these might be throttled", - CounterType.ALWAYS_COUNT); - messageInputThrottled = - debugCounters.registerCounter( - prefix, "message-input-throttled", - "Number of OpenFlow messages that were " + - "throttled due to high load from the sender", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - // TODO: more counters in messageReceived ?? - - switchDisconnectReadTimeout = - debugCounters.registerCounter( - prefix, "switch-disconnect-read-timeout", - "Number of times a switch was disconnected due " + - "due the switch failing to send OpenFlow " + - "messages or responding to OpenFlow ECHOs", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - switchDisconnectHandshakeTimeout = - debugCounters.registerCounter( - prefix, "switch-disconnect-handshake-timeout", - "Number of times a switch was disconnected " + - "because it failed to complete the handshake " + - "in time.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - switchDisconnectIOError = - debugCounters.registerCounter( - prefix, "switch-disconnect-io-error", - "Number of times a switch was disconnected " + - "due to IO errors on the switch connection.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - switchDisconnectParseError = - debugCounters.registerCounter( - prefix, "switch-disconnect-parse-error", - "Number of times a switch was disconnected " + - "because it sent an invalid packet that could " + - "not be parsed", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - - switchDisconnectSwitchStateException = - debugCounters.registerCounter( - prefix, "switch-disconnect-switch-state-exception", - "Number of times a switch was disconnected " + - "because it sent messages that were invalid " + - "given the switch connection's state.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - rejectedExecutionException = - debugCounters.registerCounter( - prefix, "rejected-execution-exception", - "TODO", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - - switchDisconnectOtherException = - debugCounters.registerCounter( - prefix, "switch-disconnect-other-exception", - "Number of times a switch was disconnected " + - "due to an exceptional situation not covered " + - "by other counters", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_ERROR); - - switchConnected = - debugCounters.registerCounter( - prefix, "switch-connected", - "Number of times a new switch connection was " + - "established", - CounterType.ALWAYS_COUNT); - - unhandledMessage = - debugCounters.registerCounter( - prefix, "unhandled-message", - "Number of times an OpenFlow message was " + - "received that the controller ignored because " + - "it was inapproriate given the switch " + - "connection's state.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - // might be less than warning - - packetInWhileSwitchIsSlave = - debugCounters.registerCounter( - prefix, "packet-in-while-switch-is-slave", - "Number of times a packet in was received " + - "from a switch that was in SLAVE role. " + - "Possibly inidicates inconsistent roles.", - CounterType.ALWAYS_COUNT); - epermErrorWhileSwitchIsMaster = - debugCounters.registerCounter( - prefix, "eperm-error-while-switch-is-master", - "Number of times a permission error was " + - "received while the switch was in MASTER role. " + - "Possibly inidicates inconsistent roles.", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - roleNotResentBecauseRolePending = - debugCounters.registerCounter( - prefix, "role-not-resent-because-role-pending", - "The controller tried to reestablish a role " + - "with a switch but did not do so because a " + - "previous role request was still pending", - CounterType.ALWAYS_COUNT); - roleRequestSent = - debugCounters.registerCounter( - prefix, "role-request-sent", - "Number of times the controller sent a role " + - "request to a switch.", - CounterType.ALWAYS_COUNT); - roleReplyTimeout = - debugCounters.registerCounter( - prefix, "role-reply-timeout", - "Number of times a role request message did not " + - "receive the expected reply from a switch", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - - roleReplyReceived = // expected RoleReply received - debugCounters.registerCounter( - prefix, "role-reply-received", - "Number of times the controller received the " + - "expected role reply message from a switch", - CounterType.ALWAYS_COUNT); - - roleReplyErrorUnsupported = - debugCounters.registerCounter( - prefix, "role-reply-error-unsupported", - "Number of times the controller received an " + - "error from a switch in response to a role " + - "request indicating that the switch does not " + - "support roles.", - CounterType.ALWAYS_COUNT); - - switchCounterRegistrationFailed = - debugCounters.registerCounter(prefix, - "switch-counter-registration-failed", - "Number of times the controller failed to " + - "register per-switch debug counters", - CounterType.ALWAYS_COUNT, - IDebugCounterService.CTR_MDATA_WARN); - } - } - - private Counters counters; - - Counters getCounters() { - return this.counters; - } - - /** - * A utility class to manage the <i>controller roles</i>. - * - * A utility class to manage the <i>controller roles</i> as opposed - * to the switch roles. The class manages the controllers current role, - * handles role change requests, and maintains the list of connected - * switch(-channel) so it can notify the switches of role changes. - * - * We need to ensure that every connected switch is always send the - * correct role. Therefore, switch add, sending of the intial role, and - * changing role need to use mutexes to ensure this. This has the ugly - * side-effect of requiring calls between controller and OFChannelHandler - * - * This class is fully thread safe. Its method can safely be called from - * any thread. - * - * @author gregor - * - */ - private class RoleManager { - // This role represents the role that has been set by setRole. This - // role might or might now have been notified to listeners just yet. - // This is updated by setRole. doSetRole() will use this value as - private Role role; - private String roleChangeDescription; - - // The current role info. This is updated /after/ dampening - // switches and - // listener notifications have been enqueued (but potentially before - // they have been dispatched) - private RoleInfo currentRoleInfo; - private final Set<OFChannelHandler> connectedChannelHandlers; - - /** - * @param role initial role - * @param roleChangeDescription initial value of the change description - * @throws NullPointerException if role or roleChangeDescription is null - * @throws IllegalArgumentException if role is EQUAL - */ - public RoleManager(Role role, String roleChangeDescription) { - if (role == null) - throw new NullPointerException("role must not be null"); - if (role == Role.EQUAL) - throw new IllegalArgumentException("role must not be EQUAL"); - if (roleChangeDescription == null) { - throw new NullPointerException("roleChangeDescription must " + - "not be null"); - } - - this.role = role; - this.roleChangeDescription = roleChangeDescription; - this.connectedChannelHandlers = new HashSet<OFChannelHandler>(); - this.currentRoleInfo = new RoleInfo(this.role, - this.roleChangeDescription, - new Date()); - } - - /** - * Add a newly connected OFChannelHandler. The channel handler is added - * we send the current role to the channel handler. All subsequent role - * changes will be send to all connected - * @param h The OFChannelHandler to add - */ - public synchronized void - addOFChannelHandlerAndSendRole(OFChannelHandler h) { - connectedChannelHandlers.add(h); - h.sendRoleRequest(this.role); - } - - /** - * Remove OFChannelHandler. E.g., due do disconnect. - * @param h The OFChannelHandler to remove. - */ - public synchronized void removeOFChannelHandler(OFChannelHandler h) { - connectedChannelHandlers.remove(h); - } - - /** - * Re-assert a role for the given channel handler. - * - * The caller specifies the role that should be reasserted. We only - * reassert the role if the controller's current role matches the - * reasserted role and there is no role request for the reasserted role - * pending. - * @param h The OFChannelHandler on which we should reassert. - * @param role The role to reassert - */ - public synchronized void reassertRole(OFChannelHandler h, Role role) { - // check if the requested reassertion actually makes sense - if (this.role != role) - return; - h.sendRoleRequestIfNotPending(this.role); - } - - /** - * Set the controller's new role and notify switches. - * - * This method updates the controllers current role and notifies all - * connected switches of the new role is different from the current - * role. We dampen calls to this method. See class description for - * details. - * - * @param role The new role. - * @param roleChangeDescription A textual description of why the role - * was changed. For information purposes only. - * @throws NullPointerException if role or roleChangeDescription is null - */ - public synchronized void setRole(Role role, String roleChangeDescription) { - if (role == null) - throw new NullPointerException("role must not be null"); - if (roleChangeDescription == null) { - throw new NullPointerException("roleChangeDescription must " + - "not be null"); - } - if (role == Role.EQUAL) { - counters.setRoleEqual.updateCounterWithFlush(); - log.debug("Received role request for EQUAL, setting to MASTER" - + " instead"); - role = Role.MASTER; - } - if (role == this.role) { - counters.setSameRole.updateCounterWithFlush(); - log.debug("Received role request for {} but controller is " - + "already {}. Ignoring it.", role, this.role); - return; - } - if (this.role == Role.MASTER && role == Role.SLAVE) { - log.info("Received role request to transition from MASTER to " - + " SLAVE (reason: {}). Terminating floodlight.", - roleChangeDescription); - System.exit(0); - } - - // At this point we are guaranteed that we will execute the code - // below exactly once during the lifetime of this process! And - // it will be a to MASTER transition - counters.setRoleMaster.updateCounterWithFlush(); - log.info("Received role request for {} (reason: {})." - + " Initiating transition", role, roleChangeDescription); - - this.role = role; - this.roleChangeDescription = roleChangeDescription; - - // TODO: we currently notify switches synchronously from the REST - // API handler. We could (should?) do this asynchronously. - currentRoleInfo = new RoleInfo(this.role, - this.roleChangeDescription, - new Date()); - Controller.this.switchManager.setRole(this.role); - for (OFChannelHandler h: connectedChannelHandlers) - h.sendRoleRequest(this.role); - - Controller.this.addUpdateToQueue(new HARoleUpdate(this.role)); - } - - /** - * Return the RoleInfo object describing the current role. - * - * Return the RoleInfo object describing the current role. The - * RoleInfo object is used by REST API users. We need to return - * a defensive copy. - * @return the current RoleInfo object - */ - public synchronized RoleInfo getRoleInfo() { - return new RoleInfo(currentRoleInfo); - } - } - - - /** - * This is a utility class to encapsulate code that deals with switch - * life cycles. It interacts with the sync store to read/write switches - * to/from the store and it maintains the switch maps. - * @author gregor - * - */ - private class SwitchManager implements IStoreListener<Long> { - private Role role; - private final ConcurrentHashMap<Long,IOFSwitch> activeSwitches; - private final ConcurrentHashMap<Long,IOFSwitch> syncedSwitches; - - public SwitchManager(Role role) { - this.role = role; - this.activeSwitches = new ConcurrentHashMap<Long, IOFSwitch>(); - this.syncedSwitches = new ConcurrentHashMap<Long, IOFSwitch>(); - } - - @Override - public void keysModified(Iterator<Long> keys, UpdateType type) { - if (type == UpdateType.LOCAL) { - // We only care for remote updates - return; - } - counters.remoteStoreNotification.updateCounterWithFlush(); - while(keys.hasNext()) { - Long key = keys.next(); - Versioned<SwitchSyncRepresentation> versionedSwitch = null; - try { - versionedSwitch = storeClient.get(key); - } catch (SyncException e) { - counters.storeSyncError.updateCounterWithFlush(); - log.error("Exception while retrieving switch " + - HexString.toHexString(key) + - " from sync store. Skipping", e); - continue; - } - if (log.isTraceEnabled()) { - log.trace("Reveiced switch store notification: key={}, " + - "entry={}", key, versionedSwitch.getValue()); - } - // versionedSwtich won't be null. storeClient.get() always - // returns a non-null or throws an exception - if (versionedSwitch.getValue() == null) { - switchRemovedFromStore(key); - continue; - } - SwitchSyncRepresentation storedSwitch = - versionedSwitch.getValue(); - IOFSwitch sw = getOFSwitchInstance(storedSwitch.getDescription()); - sw.setFeaturesReply(storedSwitch.getFeaturesReply()); - if (!key.equals(storedSwitch.getFeaturesReply().getDatapathId())) { - counters.storeSyncError.updateCounterWithFlush(); - log.error("Inconsistent DPIDs from switch sync store: " + - "key is {} but sw.getId() says {}. Ignoring", - HexString.toHexString(key), sw.getStringId()); - continue; - } - switchAddedToStore(sw); - } - } - - - public synchronized void setRole(Role role) { - this.role = role; - Runnable consolidateStoreTask = new Runnable() { - @Override - public void run() { - consolidateStore(); - } - }; - if ((role == Role.MASTER) && - this.syncedSwitches.isEmpty()) - addUpdateToQueue(new ReadyForReconcileUpdate()); - - Controller.this.ses.schedule(consolidateStoreTask, - consolidateStoreTimeDelayMs, - TimeUnit.MILLISECONDS); - } - - @LogMessageDocs({ - @LogMessageDoc(level="ERROR", - message="Switch {switch} activated but was already active", - explanation="A switch that was already activated was " + - "activated again. This should not happen.", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG - ), - @LogMessageDoc(level="WARN", - message="New switch added {switch} for already-added switch {switch}", - explanation="A switch with the same DPID as another switch " + - "connected to the controller. This can be caused by " + - "multiple switches configured with the same DPID, or " + - "by a switch reconnected very quickly after " + - "disconnecting.", - recommendation="If this happens repeatedly, it is likely there " + - "are switches with duplicate DPIDs on the network. " + - "Reconfigure the appropriate switches. If it happens " + - "very rarely, then it is likely this is a transient " + - "network problem that can be ignored." - ) - }) - /** - * Called when a switch is activated, i.e., when it enters master - * role relative to this controller. - * @param sw - */ - public synchronized void switchActivated(IOFSwitch sw) { - if (role != Role.MASTER) { - counters.invalidSwitchActivatedWhileSlave.updateCounterWithFlush(); - return; // only react to switch connections when master - // FIXME: should we disconnect the switch? When can this happen? - } - Long dpid = sw.getId(); - counters.switchActivated.updateCounterWithFlush(); - IOFSwitch oldSw = this.activeSwitches.put(dpid, sw); - // Update event history - evSwitch.updateEventWithFlush(new SwitchEvent(dpid, "connected")); - - if (oldSw == sw) { - // Note == for object equality, not .equals for value - // TODO: should we wipe the flow table if - // alwaysClearFlowsOnSwAdd is set? OTOH this case should - // really never happen. - counters.errorSameSwitchReactivated.updateCounterWithFlush(); - log.error("Switch {} activated but was already active", sw); - addSwitchToStore(sw); - return; - } - - if (oldSw != null) { - // This happens either when we have switches with duplicate - // DPIDs or when a switch reconnects before we saw the - // disconnect - counters.switchWithSameDpidActivated.updateCounterWithFlush(); - log.warn("New switch added {} for already-added switch {}", - sw, oldSw); - // We need to disconnect and remove the old switch - // TODO: we notify switch listeners that the switch has been - // removed and then we notify them that the new one has been - // added. One could argue that a switchChanged notification - // might be more appropriate in this case.... - oldSw.cancelAllStatisticsReplies(); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.REMOVED)); - oldSw.disconnectOutputStream(); - // Add the new switch and clear FlowMods - // TODO: if this is the same switch re-connecting rather than - // a DPID collision it would make sense to not wipe the flow - // table. - sw.clearAllFlowMods(); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.ADDED)); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.ACTIVATED)); - addSwitchToStore(sw); - return; - } - - IOFSwitch storedSwitch = this.syncedSwitches.remove(sw.getId()); - if (storedSwitch == null) { - // The switch isn't known to the controller cluster. We - // need to send a switchAdded notification and clear all - // flows. - if (!swConnectCache.update(sw.getId())) - sw.clearAllFlowMods(); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.ADDED)); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.ACTIVATED)); - counters.newSwitchActivated.updateCounterWithFlush(); - } else { - // FIXME: switch was in store. check if ports or anything else - // has changed and send update. - if (alwaysClearFlowsOnSwActivate) { - sw.clearAllFlowMods(); - } - if (sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)) { - // We have a stored switch and the newly activated switch - // supports roles. This indicates that the switch was - // previously connected as slave. Since we don't update - // ports while slave, we need to set the ports on the - // new switch from the ports on the stored switch - // No need to send notifications, since we've dispatched - // them as we receive them from the store - sw.setPorts(storedSwitch.getPorts()); - } - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.ACTIVATED)); - sendNotificationsIfSwitchDiffers(storedSwitch, sw); - counters.syncedSwitchActivated.updateCounterWithFlush(); - if (this.syncedSwitches.isEmpty()) { - // we have just activated the last synced switch. I.e., - // all previously known switch are now active. Send - // notification - // update dispatcher will increment counter - addUpdateToQueue(new ReadyForReconcileUpdate()); - } - } - addSwitchToStore(sw); - } - - /** - * Called when ports on the given switch have changed. Writes the - * updated switch to the sync store and queues a switch notification - * to listeners - * @param sw - */ - public synchronized void switchPortsChanged(IOFSwitch sw, - ImmutablePort port, - PortChangeType type) { - if (role != Role.MASTER) { - counters.invalidPortsChanged.updateCounterWithFlush(); - return; - } - if (!this.activeSwitches.containsKey(sw.getId())) { - counters.invalidPortsChanged.updateCounterWithFlush(); - return; - } - // update switch in store - addSwitchToStore(sw); - // no need to count here. SwitchUpdate.dispatch will count - // the portchanged - SwitchUpdate update = new SwitchUpdate(sw.getId(), - SwitchUpdateType.PORTCHANGED, - port, type); - addUpdateToQueue(update); - } - - /** - * Called when we receive a store notification about a new or updated - * switch. - * @param sw - */ - private synchronized void switchAddedToStore(IOFSwitch sw) { - if (role != Role.SLAVE) { - counters.invalidStoreEventWhileMaster.updateCounterWithFlush(); - return; // only read from store if slave - } - Long dpid = sw.getId(); - - IOFSwitch oldSw = syncedSwitches.put(dpid, sw); - if (oldSw == null) { - counters.newSwitchFromStore.updateCounterWithFlush(); - addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED)); - } else { - // The switch already exists in storage, see if anything - // has changed - sendNotificationsIfSwitchDiffers(oldSw, sw); - counters.updatedSwitchFromStore.updateCounterWithFlush(); - } - } - - /** - * Called when we receive a store notification about a switch that - * has been removed from the sync store - * @param dpid - */ - private synchronized void switchRemovedFromStore(long dpid) { - if (role != Role.SLAVE) { - counters.invalidStoreEventWhileMaster.updateCounterWithFlush(); - return; // only read from store if slave - } - IOFSwitch oldSw = syncedSwitches.remove(dpid); - if (oldSw != null) { - counters.syncedSwitchRemoved.updateCounterWithFlush(); - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.REMOVED)); - } else { - // TODO: the switch was deleted (tombstone) before we ever - // knew about it (or was deleted repeatedly). Can this - // happen? When/how? - counters.unknownSwitchRemovedFromStore.updateCounterWithFlush(); - } - } - - public synchronized void switchDeactivated(IOFSwitch sw) { - // ignore. we don't handle MASTER -> SLAVE transitions. We - // expect a restart - } - - /** - * Called when a switch disconnects - * @param sw - */ - public synchronized void switchDisconnected(IOFSwitch sw) { - if (role == Role.SLAVE) { - counters.switchDisconnectedWhileSlave.updateCounterWithFlush(); - return; // only react to switch connections when master - } - long dpid = sw.getId(); - // Update event history - // TODO: this is asymmetric with respect to connect event - // in switchActivated(). Should we have events on the - // slave as well? - evSwitch.updateEventWithFlush(new SwitchEvent(dpid, "disconnected")); - counters.switchDisconnected.updateCounterWithFlush(); - IOFSwitch oldSw = this.activeSwitches.get(dpid); - if (oldSw != sw) { - // This can happen if the disconnected switch was inactive - // (SLAVE) then oldSw==null. Or if we previously had the - // "added switch for already added switch case". - // Either way we shouldn't notify or do anything else - log.debug("removeSwitch called for switch {} but have {} in" - + " activeSwitches map. Ignoring", sw, oldSw); - return; - } - log.debug("removeSwitch {}", sw); - swConnectCache.update(sw.getId()); - this.activeSwitches.remove(sw.getId()); - removeSwitchFromStore(sw.getId()); - // We cancel all outstanding statistics replies if the switch transition - // from active. In the future we might allow statistics requests - // from slave controllers. Then we need to move this cancelation - // to switch disconnect - sw.cancelAllStatisticsReplies(); - addUpdateToQueue(new SwitchUpdate(sw.getId(), - SwitchUpdateType.REMOVED)); - } - - /** - * Write the given switch to the sync store. - * @param sw - */ - private synchronized void addSwitchToStore(IOFSwitch sw) { - // Add to store - // FIXME: do we need to use a put that takes a versioned here? - // need to verify - try { - storeClient.put(sw.getId(), new SwitchSyncRepresentation(sw)); - } catch (ObsoleteVersionException e) { - // FIXME: what's the right behavior here. Can the store client - // even throw this error? Should not since all local store - // access is synchronized - } catch (SyncException e) { - counters.storeSyncError.updateCounterWithFlush(); - log.error("Could not write switch " + sw.getStringId() + - " to sync store:", e); - } - } - - /** - * Write the given switch to the sync store if it's not already - * there - * TODO: should this be merged with addSwitchToStore - * @param sw - * @return true if the switch was absent, false otherwise - */ - private synchronized boolean addSwitchToStoreIfAbsent(IOFSwitch sw) { - try { - Versioned<SwitchSyncRepresentation> versionedSSr = - storeClient.get(sw.getId()); - if (versionedSSr.getValue() == null) { - // switch is absent - versionedSSr.setValue(new SwitchSyncRepresentation(sw)); - storeClient.put(sw.getId(), versionedSSr); - return true; - } else { - return false; - } - } catch (ObsoleteVersionException e) { - // FIXME: what's the right behavior here. Can the store client - // even throw this error? Should not since all local store - // access is synchronized - } catch (SyncException e) { - counters.storeSyncError.updateCounterWithFlush(); - log.error("Could not write switch " + sw.getStringId() + - " to sync store:", e); - } - return false; - } - - /** - * Remove the given switch from the sync store. - * @param dpid - */ - private synchronized void removeSwitchFromStore(long dpid) { - try { - storeClient.delete(dpid); - } catch (SyncException e) { - counters.storeSyncError.updateCounterWithFlush(); - // ObsoleteVerisonException can't happend because all - // store modifications are synchronized - log.error("Could not remove switch " + - HexString.toHexString(dpid) + - " from sync store:", e); - } - } - - /** - * Check if the two switches differ in their ports or in other - * fields and if they differ enqueue a switch update - * @param oldSw - * @param newSw - */ - private synchronized void - sendNotificationsIfSwitchDiffers(IOFSwitch oldSw, - IOFSwitch newSw) { - Collection<PortChangeEvent> portDiffs = - oldSw.comparePorts(newSw.getPorts()); - for (PortChangeEvent ev: portDiffs) { - SwitchUpdate update = - new SwitchUpdate(newSw.getId(), - SwitchUpdateType.PORTCHANGED, - ev.port, ev.type); - addUpdateToQueue(update); - } - } - /** - * Remove all entries from the store that don't correspond to an - * active switch. - * TODO: is it a problem that this is fully synchronized - */ - private synchronized void consolidateStore() { - if (role == Role.SLAVE) - return; - boolean shouldNotifyReadyForReconcile = false; - counters.consolidateStoreRunCount.updateCounterWithFlush(); - log.info("Consolidating synced switches after MASTER transition"); - IClosableIterator<Map.Entry<Long,Versioned<SwitchSyncRepresentation>>> - iter = null; - try { - iter = storeClient.entries(); - } catch (SyncException e) { - counters.storeSyncError.updateCounterWithFlush(); - log.error("Failed to read switches from sync store", e); - return; - } - try { - while(iter.hasNext()) { - Entry<Long, Versioned<SwitchSyncRepresentation>> entry = - iter.next(); - if (!this.activeSwitches.containsKey(entry.getKey())) { - removeSwitchFromStore(entry.getKey()); - if (this.syncedSwitches.remove(entry.getKey()) != null) { - // a switch that's in the store and in synced - // switches but that is not active. I.e., a - // switch known to the old master that hasn't - // reconnected to this controller. - counters.switchesNotReconnectingToNewMaster - .updateCounterWithFlush(); - shouldNotifyReadyForReconcile = true; - addUpdateToQueue(new SwitchUpdate(entry.getKey(), - SwitchUpdateType.REMOVED)); - } else { - // A switch was in the store but it's neither in - // activeSwitches nor syncedSwitches. This could - // happen if the old Master has added this entry - // to the store after this controller has - // stopped reacting to store notifications (due - // to MASTER transition) - counters.consolidateStoreInconsistencies - .updateCounterWithFlush(); - } - } - } - } finally { - if (iter != null) - iter.close(); - } - // In general, syncedSwitches should now be empty. However, - // the old Master could have removed a switch from the store - // after this controller has stopped reacting to store - // notification (because it's now MASTER). We need to remove - // these switches. - Iterator<Long> it = this.syncedSwitches.keySet().iterator(); - while (it.hasNext()) { - counters.switchesNotReconnectingToNewMaster.updateCounterWithFlush(); - counters.consolidateStoreInconsistencies.updateCounterWithFlush(); - Long dpid = it.next(); - shouldNotifyReadyForReconcile = true; - addUpdateToQueue(new SwitchUpdate(dpid, - SwitchUpdateType.REMOVED)); - it.remove(); - } - if (shouldNotifyReadyForReconcile) { - // at least one previously known switch has been removed. - addUpdateToQueue(new ReadyForReconcileUpdate()); - } - - // FIXME: do we need this final check here. - // Now iterate through all active switches and determine if - // any of them are missing from the sync store. This can only - // happen if another controller has removed them (because we know - // that we have written them to the store). - for (IOFSwitch sw: this.activeSwitches.values()) { - if (addSwitchToStoreIfAbsent(sw)) - counters.consolidateStoreInconsistencies.updateCounterWithFlush(); - } - } - - // FIXME: remove this method - public Map<Long,IOFSwitch> getAllSwitchMap() { - // this.syncedSwitches will be empty after the master transition - Map<Long,IOFSwitch> switches = - new HashMap<Long, IOFSwitch>(this.syncedSwitches); - if (this.role != Role.SLAVE) - switches.putAll(this.activeSwitches); - return switches; - } - - public Set<Long> getAllSwitchDpids() { - // this.syncedSwitches will be empty after the master transition - Set<Long> dpids = new HashSet<Long>(this.syncedSwitches.keySet()); - if (this.role != Role.SLAVE) - dpids.addAll(this.activeSwitches.keySet()); - return dpids; - } - - public IOFSwitch getSwitch(long dpid) { - if (this.role == Role.SLAVE) - return this.syncedSwitches.get(dpid); - // MASTER: if the switch is found in the active map return - // otherwise look up the switch in the bigSync map. The bigSync map - // wil be cleared after the transition is complete. - IOFSwitch sw = this.activeSwitches.get(dpid); - if (sw != null) - return sw; - return this.syncedSwitches.get(dpid); - } - - public void addSwitchEvent(long dpid, String reason, boolean flushNow) { - if (flushNow) - evSwitch.updateEventWithFlush(new SwitchEvent(dpid, reason)); - else - evSwitch.updateEventNoFlush(new SwitchEvent(dpid, reason)); - } - - } - - - /** - * Updates handled by the main loop - */ - interface IUpdate { - /** - * Calls the appropriate listeners - */ - public void dispatch(); - } - - /** - * Update message that indicates that the controller can now start - * flow reconciliation after a SLAVE->MASTER transition - */ - private class ReadyForReconcileUpdate implements IUpdate { - @Override - public void dispatch() { - counters.readyForReconcile.updateCounterWithFlush(); - if (readyForReconcileListeners != null) { - for (IReadyForReconcileListener listener: - readyForReconcileListeners) { - listener.readyForReconcile(); - } - } - } - } - - enum SwitchUpdateType { - ADDED, - REMOVED, - ACTIVATED, - DEACTIVATED, - PORTCHANGED, - OTHERCHANGE - } - /** - * Update message indicating a switch was added or removed - */ - private class SwitchUpdate implements IUpdate { - private final long swId; - private final SwitchUpdateType switchUpdateType; - private final ImmutablePort port; - private final PortChangeType changeType; - - - public SwitchUpdate(long swId, SwitchUpdateType switchUpdateType) { - this(swId, switchUpdateType, null, null); - } - public SwitchUpdate(long swId, - SwitchUpdateType switchUpdateType, - ImmutablePort port, - PortChangeType changeType) { - if (switchUpdateType == SwitchUpdateType.PORTCHANGED) { - if (port == null) { - throw new NullPointerException("Port must not be null " + - "for PORTCHANGED updates"); - } - if (changeType == null) { - throw new NullPointerException("ChangeType must not be " + - "null for PORTCHANGED updates"); - } - } else { - if (port != null || changeType != null) { - throw new IllegalArgumentException("port and changeType " + - "must be null for " + switchUpdateType + - " updates"); - } - } - this.swId = swId; - this.switchUpdateType = switchUpdateType; - this.port = port; - this.changeType = changeType; - } - @Override - public void dispatch() { - if (log.isTraceEnabled()) { - log.trace("Dispatching switch update {} {}", - HexString.toHexString(swId), switchUpdateType); - } - if (switchListeners != null) { - for (IOFSwitchListener listener : switchListeners) { - switch(switchUpdateType) { - case ADDED: - // don't count here. We have more specific - // counters before the update is created - listener.switchAdded(swId); - break; - case REMOVED: - // don't count here. We have more specific - // counters before the update is created - listener.switchRemoved(swId); - break; - case PORTCHANGED: - counters.switchPortChanged.updateCounterWithFlush(); - listener.switchPortChanged(swId, port, changeType); - break; - case ACTIVATED: - // don't count here. We have more specific - // counters before the update is created - listener.switchActivated(swId); - break; - case DEACTIVATED: - // ignore - break; - case OTHERCHANGE: - counters.switchOtherChange.updateCounterWithFlush(); - listener.switchChanged(swId); - break; - } - } - } - } - } - - /** - * Update message indicating controller's role has changed. - * RoleManager, which enqueues these updates gurantees that we will - * only have a single transition from SLAVE to MASTER. - */ - private class HARoleUpdate implements IUpdate { - private final Role newRole; - public HARoleUpdate(Role newRole) { - if (newRole != Role.MASTER) - throw new IllegalArgumentException("Only legal role change is" - + "to MASTER. Got to " - + newRole); - this.newRole = newRole; - } - @Override - public void dispatch() { - if (log.isDebugEnabled()) { - log.debug("Dispatching HA Role update newRole = {}", - newRole); - } - for (IHAListener listener : haListeners.getOrderedListeners()) { - if (log.isTraceEnabled()) { - log.trace("Calling HAListener {} with transitionToMaster", - listener.getName()); - } - listener.transitionToMaster(); - } - if (newRole != Role.SLAVE) { - Controller.this.notifiedRole = newRole; - } - } - } - - /** - * Update message indicating - * IPs of controllers in controller cluster have changed. - */ - private class HAControllerNodeIPUpdate implements IUpdate { - public final Map<String,String> curControllerNodeIPs; - public final Map<String,String> addedControllerNodeIPs; - public final Map<String,String> removedControllerNodeIPs; - public HAControllerNodeIPUpdate( - HashMap<String,String> curControllerNodeIPs, - HashMap<String,String> addedControllerNodeIPs, - HashMap<String,String> removedControllerNodeIPs) { - this.curControllerNodeIPs = curControllerNodeIPs; - this.addedControllerNodeIPs = addedControllerNodeIPs; - this.removedControllerNodeIPs = removedControllerNodeIPs; - } - @Override - public void dispatch() { - if (log.isTraceEnabled()) { - log.trace("Dispatching HA Controller Node IP update " - + "curIPs = {}, addedIPs = {}, removedIPs = {}", - new Object[] { curControllerNodeIPs, addedControllerNodeIPs, - removedControllerNodeIPs } - ); - } - if (haListeners != null) { - for (IHAListener listener: haListeners.getOrderedListeners()) { - listener.controllerNodeIPsChanged(curControllerNodeIPs, - addedControllerNodeIPs, removedControllerNodeIPs); - } - } - } - } - - // *************** - // Getters/Setters - // *************** - - void setStorageSourceService(IStorageSourceService storageSource) { - this.storageSource = storageSource; - } - - IStorageSourceService getStorageSourceService() { - return this.storageSource; - } - - void setCounterStore(ICounterStoreService counterStore) { - this.counterStore = counterStore; - } - - void setDebugCounter(IDebugCounterService debugCounters) { - this.debugCounters = debugCounters; - } - - public void setDebugEvent(IDebugEventService debugEvent) { - this.debugEvents = debugEvent; - } - - IDebugCounterService getDebugCounter() { - return this.debugCounters; - } - - void setSyncService(ISyncService syncService) { - this.syncService = syncService; - } - void setPktInProcessingService(IPktInProcessingTimeService pits) { - this.pktinProcTime = pits; - } - - void setRestApiService(IRestApiService restApi) { - this.restApi = restApi; - } - - void setThreadPoolService(IThreadPoolService tp) { - this.threadPool = tp; - } - - IThreadPoolService getThreadPoolService() { - return this.threadPool; - } - - @Override - public Role getRole() { - // FIXME: - return notifiedRole; - } - - @Override - public RoleInfo getRoleInfo() { - return roleManager.getRoleInfo(); - } - - @Override - public void setRole(Role role, String roleChangeDescription) { - roleManager.setRole(role, roleChangeDescription); - } - - // **************** - // Message handlers - // **************** - - /** - * Indicates that ports on the given switch have changed. Enqueue a - * switch update. - * @param sw - */ - void notifyPortChanged(IOFSwitch sw, - ImmutablePort port, - PortChangeType changeType) { - if (sw == null) { - String msg = String.format("Switch must not be null. " + - "port=%s, changeType=%s", port, changeType); - throw new NullPointerException(msg); - } - if (port == null) { - String msg = String.format("Port must not be null. " + - "switch=%s, changeType=%s", sw, changeType); - throw new NullPointerException(msg); - } - if (changeType == null) { - String msg = String.format("ChangeType must not be null. " + - "switch=%s, port=%s", sw, port); - throw new NullPointerException(msg); - } - this.switchManager.switchPortsChanged(sw, port, changeType); - } - - /** - * flcontext_cache - Keep a thread local stack of contexts - */ - protected static final ThreadLocal<Stack<FloodlightContext>> flcontext_cache = - new ThreadLocal <Stack<FloodlightContext>> () { - @Override - protected Stack<FloodlightContext> initialValue() { - return new Stack<FloodlightContext>(); - } - }; - - /** - * flcontext_alloc - pop a context off the stack, if required create a new one - * @return FloodlightContext - */ - protected static FloodlightContext flcontext_alloc() { - FloodlightContext flcontext = null; - - if (flcontext_cache.get().empty()) { - flcontext = new FloodlightContext(); - } - else { - flcontext = flcontext_cache.get().pop(); - } - - return flcontext; - } - - /** - * flcontext_free - Free the context to the current thread - * @param flcontext - */ - protected void flcontext_free(FloodlightContext flcontext) { - flcontext.getStorage().clear(); - flcontext_cache.get().push(flcontext); - } - - - /** - * - * Handle and dispatch a message to IOFMessageListeners. - * - * We only dispatch messages to listeners if the controller's role is MASTER. - * - * @param sw The switch sending the message - * @param m The message the switch sent - * @param flContext The floodlight context to use for this message. If - * null, a new context will be allocated. - * @throws IOException - * - * FIXME: this method and the ChannelHandler disagree on which messages - * should be dispatched and which shouldn't - */ - @LogMessageDocs({ - @LogMessageDoc(level="ERROR", - message="Ignoring PacketIn (Xid = {xid}) because the data" + - " field is empty.", - explanation="The switch sent an improperly-formatted PacketIn" + - " message", - recommendation=LogMessageDoc.CHECK_SWITCH), - @LogMessageDoc(level="WARN", - message="Unhandled OF Message: {} from {}", - explanation="The switch sent a message not handled by " + - "the controller") - }) - protected void handleMessage(IOFSwitch sw, OFMessage m, - FloodlightContext bContext) - throws IOException { - Ethernet eth = null; - - if (this.notifiedRole == Role.SLAVE) { - counters.dispatchMessageWhileSlave.updateCounterNoFlush(); - // We are SLAVE. Do not dispatch messages to listeners. - return; - } - counters.dispatchMessage.updateCounterNoFlush(); - - switch (m.getType()) { - case PACKET_IN: - OFPacketIn pi = (OFPacketIn)m; - - if (pi.getPacketData().length <= 0) { - log.error("Ignoring PacketIn (Xid = " + pi.getXid() + - ") because the data field is empty."); - return; - } - - if (Controller.ALWAYS_DECODE_ETH) { - eth = new Ethernet(); - eth.deserialize(pi.getPacketData(), 0, - pi.getPacketData().length); - counterStore.updatePacketInCountersLocal(sw, m, eth); - } - // fall through to default case... - - default: - - List<IOFMessageListener> listeners = null; - if (messageListeners.containsKey(m.getType())) { - listeners = messageListeners.get(m.getType()). - getOrderedListeners(); - } - - FloodlightContext bc = null; - if (listeners != null) { - // Check if floodlight context is passed from the calling - // function, if so use that floodlight context, otherwise - // allocate one - if (bContext == null) { - bc = flcontext_alloc(); - } else { - bc = bContext; - } - if (eth != null) { - IFloodlightProviderService.bcStore.put(bc, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD, - eth); - } - - // Get the starting time (overall and per-component) of - // the processing chain for this packet if performance - // monitoring is turned on - pktinProcTime.recordStartTimePktIn(); - Command cmd; - for (IOFMessageListener listener : listeners) { - pktinProcTime.recordStartTimeComp(listener); - cmd = listener.receive(sw, m, bc); - pktinProcTime.recordEndTimeComp(listener); - - if (Command.STOP.equals(cmd)) { - break; - } - } - pktinProcTime.recordEndTimePktIn(sw, m, bc); - } else { - if (m.getType() != OFType.BARRIER_REPLY) - log.warn("Unhandled OF Message: {} from {}", m, sw); - else - log.debug("Received a Barrier Reply, no listeners for it"); - } - - if ((bContext == null) && (bc != null)) flcontext_free(bc); - } - } - - void switchActivated(IOFSwitch sw) { - this.switchManager.switchActivated(sw); - } - - void switchDeactivated(IOFSwitch sw) { - this.switchManager.switchDeactivated(sw); - } - - void switchDisconnected(IOFSwitch sw) { - this.switchManager.switchDisconnected(sw); - } - - // *************** - // IFloodlightProvider - // *************** - - /** - * Forward to RoleManager - * @param h - */ - void addSwitchChannelAndSendInitialRole(OFChannelHandler h) { - roleManager.addOFChannelHandlerAndSendRole(h); - } - - /** - * Forwards to RoleManager - * @param h - */ - void removeSwitchChannel(OFChannelHandler h) { - roleManager.removeOFChannelHandler(h); - } - - /** - * Forwards to RoleManager - * @param h - * @param role - */ - void reassertRole(OFChannelHandler h, Role role) { - roleManager.reassertRole(h, role); - } - - // FIXME: remove this method - @Override - public Map<Long,IOFSwitch> getAllSwitchMap() { - return this.switchManager.getAllSwitchMap(); - } - - @Override - public Set<Long> getAllSwitchDpids() { - return this.switchManager.getAllSwitchDpids(); - } - - @Override - public IOFSwitch getSwitch(long dpid) { - return this.switchManager.getSwitch(dpid); - } - - @Override - public void addOFSwitchListener(IOFSwitchListener listener) { - this.switchListeners.add(listener); - } - - @Override - public void removeOFSwitchListener(IOFSwitchListener listener) { - this.switchListeners.remove(listener); - } - - @Override - public synchronized void addOFMessageListener(OFType type, - IOFMessageListener listener) { - ListenerDispatcher<OFType, IOFMessageListener> ldd = - messageListeners.get(type); - if (ldd == null) { - ldd = new ListenerDispatcher<OFType, IOFMessageListener>(); - messageListeners.put(type, ldd); - } - ldd.addListener(type, listener); - } - - @Override - public synchronized void removeOFMessageListener(OFType type, - IOFMessageListener listener) { - ListenerDispatcher<OFType, IOFMessageListener> ldd = - messageListeners.get(type); - if (ldd != null) { - ldd.removeListener(listener); - } - } - - private void logListeners() { - for (Map.Entry<OFType, - ListenerDispatcher<OFType, - IOFMessageListener>> entry - : messageListeners.entrySet()) { - - OFType type = entry.getKey(); - ListenerDispatcher<OFType, IOFMessageListener> ldd = - entry.getValue(); - - StringBuilder sb = new StringBuilder(); - sb.append("OFListeners for "); - sb.append(type); - sb.append(": "); - for (IOFMessageListener l : ldd.getOrderedListeners()) { - sb.append(l.getName()); - sb.append(","); - } - log.debug(sb.toString()); - } - - StringBuilder sb = new StringBuilder(); - sb.append("HAListeners: "); - for (IHAListener l: haListeners.getOrderedListeners()) { - sb.append(l.getName()); - sb.append(", "); - } - log.debug(sb.toString()); - } - - public void removeOFMessageListeners(OFType type) { - messageListeners.remove(type); - } - - @Override - public Map<OFType, List<IOFMessageListener>> getListeners() { - Map<OFType, List<IOFMessageListener>> lers = - new HashMap<OFType, List<IOFMessageListener>>(); - for(Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> e : - messageListeners.entrySet()) { - lers.put(e.getKey(), e.getValue().getOrderedListeners()); - } - return Collections.unmodifiableMap(lers); - } - - @Override - @LogMessageDocs({ - @LogMessageDoc(level="ERROR", - message="Error reinjecting OFMessage on switch {switch}", - explanation="An I/O error occured while attempting to " + - "process an OpenFlow message", - recommendation=LogMessageDoc.CHECK_SWITCH) - }) - public boolean injectOfMessage(IOFSwitch sw, OFMessage msg, - FloodlightContext bc) { - if (sw == null) - throw new NullPointerException("Switch must not be null"); - if (msg == null) - throw new NullPointerException("OFMessage must not be null"); - - // FIXME: Do we need to be able to inject messages from switches - // where we're the slave controller (i.e. they're connected but - // not active)? - if (!sw.isActive()) return false; - - try { - // Pass Floodlight context to the handleMessages() - handleMessage(sw, msg, bc); - } catch (IOException e) { - log.error("Error reinjecting OFMessage on switch {}", - sw.getStringId()); - return false; - } - return true; - } - - @Override - @LogMessageDoc(message="Calling System.exit", - explanation="The controller is terminating") - public synchronized void terminate() { - log.info("Calling System.exit"); - System.exit(1); - } - - @Override - public boolean injectOfMessage(IOFSwitch sw, OFMessage msg) { - // call the overloaded version with floodlight context set to null - return injectOfMessage(sw, msg, null); - } - - @Override - public void handleOutgoingMessage(IOFSwitch sw, OFMessage m, - FloodlightContext bc) { - if (sw == null) - throw new NullPointerException("Switch must not be null"); - if (m == null) - throw new NullPointerException("OFMessage must not be null"); - if (bc == null) - bc = new FloodlightContext(); - if (log.isTraceEnabled()) { - String str = OFMessage.getDataAsString(sw, m, bc); - log.trace("{}", str); - } - - List<IOFMessageListener> listeners = null; - if (messageListeners.containsKey(m.getType())) { - listeners = - messageListeners.get(m.getType()).getOrderedListeners(); - } - - if (listeners != null) { - for (IOFMessageListener listener : listeners) { - if (Command.STOP.equals(listener.receive(sw, m, bc))) { - break; - } - } - } - } - - @Override - public BasicFactory getOFMessageFactory() { - return factory; - } - - // ************** - // Initialization - // ************** - - - /** - * Sets the initial role based on properties in the config params. - * It looks for two different properties. - * If the "role" property is specified then the value should be - * either "EQUAL", "MASTER", or "SLAVE" and the role of the - * controller is set to the specified value. If the "role" property - * is not specified then it looks next for the "role.path" property. - * In this case the value should be the path to a property file in - * the file system that contains a property called "floodlight.role" - * which can be one of the values listed above for the "role" property. - * The idea behind the "role.path" mechanism is that you have some - * separate heartbeat and master controller election algorithm that - * determines the role of the controller. When a role transition happens, - * it updates the current role in the file specified by the "role.path" - * file. Then if floodlight restarts for some reason it can get the - * correct current role of the controller from the file. - * @param configParams The config params for the FloodlightProvider service - * @return A valid role if role information is specified in the - * config params, otherwise null - */ - @LogMessageDocs({ - @LogMessageDoc(message="Controller role set to {role}", - explanation="Setting the initial HA role to "), - @LogMessageDoc(level="ERROR", - message="Invalid current role value: {role}", - explanation="An invalid HA role value was read from the " + - "properties file", - recommendation=LogMessageDoc.CHECK_CONTROLLER) - }) - protected Role getInitialRole(Map<String, String> configParams) { - Role role = Role.MASTER; - String roleString = configParams.get("role"); - if (roleString == null) { - String rolePath = configParams.get("rolepath"); - if (rolePath != null) { - Properties properties = new Properties(); - try { - properties.load(new FileInputStream(rolePath)); - roleString = properties.getProperty("floodlight.role"); - } - catch (IOException exc) { - // Don't treat it as an error if the file specified by the - // rolepath property doesn't exist. This lets us enable the - // HA mechanism by just creating/setting the floodlight.role - // property in that file without having to modify the - // floodlight properties. - } - } - } - - if (roleString != null) { - // Canonicalize the string to the form used for the enum constants - roleString = roleString.trim().toUpperCase(); - try { - role = Role.valueOf(roleString); - } - catch (IllegalArgumentException exc) { - log.error("Invalid current role value: {}", roleString); - } - } - if (role == Role.EQUAL) - role = Role.MASTER; - - log.info("Controller role set to {}", role); - - return role; - } - - /** - * Tell controller that we're ready to accept switches loop - * @throws IOException - */ - @Override - @LogMessageDocs({ - @LogMessageDoc(message="Listening for switch connections on {address}", - explanation="The controller is ready and listening for new" + - " switch connections"), - @LogMessageDoc(message="Storage exception in controller " + - "updates loop; terminating process", - explanation=ERROR_DATABASE, - recommendation=LogMessageDoc.CHECK_CONTROLLER), - @LogMessageDoc(level="ERROR", - message="Exception in controller updates loop", - explanation="Failed to dispatch controller event", - recommendation=LogMessageDoc.GENERIC_ACTION) - }) - public void run() { - if (log.isDebugEnabled()) { - logListeners(); - } - - try { - final ServerBootstrap bootstrap = createServerBootStrap(); - - bootstrap.setOption("reuseAddr", true); - bootstrap.setOption("child.keepAlive", true); - bootstrap.setOption("child.tcpNoDelay", true); - bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); - - ChannelPipelineFactory pfact = - new OpenflowPipelineFactory(this, null); - bootstrap.setPipelineFactory(pfact); - InetSocketAddress sa = - (openFlowHost == null) - ? new InetSocketAddress(openFlowPort) - : new InetSocketAddress(openFlowHost, openFlowPort); - final ChannelGroup cg = new DefaultChannelGroup(); - cg.add(bootstrap.bind(sa)); - - log.info("Listening for switch connections on {}", sa); - } catch (Exception e) { - throw new RuntimeException(e); - } - - // main loop - while (true) { - try { - IUpdate update = updates.take(); - update.dispatch(); - } catch (InterruptedException e) { - log.error("Received interrupted exception in updates loop;" + - "terminating process"); - terminate(); - } catch (StorageException e) { - log.error("Storage exception in controller " + - "updates loop; terminating process", e); - terminate(); - } catch (Exception e) { - log.error("Exception in controller updates loop", e); - } - } - } - - private ServerBootstrap createServerBootStrap() { - if (workerThreads == 0) { - return new ServerBootstrap( - new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool())); - } else { - return new ServerBootstrap( - new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool(), workerThreads)); - } - } - - private void setConfigParams(Map<String, String> configParams) { - String ofPort = configParams.get("openflowport"); - if (ofPort != null) { - this.openFlowPort = Integer.parseInt(ofPort); - } - log.debug("OpenFlow port set to {}", this.openFlowPort); - String threads = configParams.get("workerthreads"); - if (threads != null) { - this.workerThreads = Integer.parseInt(threads); - } - log.debug("Number of worker threads set to {}", this.workerThreads); - - } - - private void initVendorMessages() { - // Configure openflowj to be able to parse the role request/reply - // vendor messages. - OFNiciraVendorExtensions.initialize(); - - // Register the standard Vendor actions that we support - OFVendorActions.registerStandardVendorActions(); - } - - /** - * Initialize internal data structures - */ - public void init(Map<String, String> configParams) { - // These data structures are initialized here because other - // module's startUp() might be called before ours - this.messageListeners = - new ConcurrentHashMap<OFType, - ListenerDispatcher<OFType, - IOFMessageListener>>(); - this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); - // add switch notification listener - this.addOFSwitchListener(new NotificationSwitchListener()); - this.readyForReconcileListeners = - new CopyOnWriteArraySet<IReadyForReconcileListener>(); - this.haListeners = - new ListenerDispatcher<HAListenerTypeMarker, IHAListener>(); - this.driverRegistry = new NaiiveSwitchDriverRegistry(); - this.controllerNodeIPsCache = new HashMap<String, String>(); - this.updates = new LinkedBlockingQueue<IUpdate>(); - this.factory = BasicFactory.getInstance(); - this.providerMap = new HashMap<String, List<IInfoProvider>>(); - setConfigParams(configParams); - Role initialRole = getInitialRole(configParams); - this.notifiedRole = initialRole; - initVendorMessages(); - - String option = configParams.get("flushSwitchesOnReconnect"); - - if (option != null && option.equalsIgnoreCase("true")) { - this.setAlwaysClearFlowsOnSwActivate(true); - log.info("Flush switches on reconnect -- Enabled."); - } else { - this.setAlwaysClearFlowsOnSwActivate(false); - log.info("Flush switches on reconnect -- Disabled"); - } - - uplinkPortPrefixSet = new HashSet<String>(); - uplinkPortPrefixSet.add("eth"); - uplinkPortPrefixSet.add("bond"); - String str = configParams.get("uplinkPortPrefix"); - if (str != null) { - List<String> items = Arrays.asList(str.split("\\s*,\\s*")); - if (items != null) { - for (String s: items) { - if (s.length() > 0) { - uplinkPortPrefixSet.add(s); - } - } - } - } - - this.roleManager = new RoleManager(this.notifiedRole, - INITIAL_ROLE_CHANGE_DESCRIPTION); - this.switchManager = new SwitchManager(this.notifiedRole); - this.counters = new Counters(); - this.swConnectCache = - new TimedCache<Long>(100, 5*1000 ); // 5 seconds interval - } - - /** - * Startup all of the controller's components - */ - @LogMessageDoc(message="Waiting for storage source", - explanation="The system database is not yet ready", - recommendation="If this message persists, this indicates " + - "that the system database has failed to start. " + - LogMessageDoc.CHECK_CONTROLLER) - public void startupComponents() throws FloodlightModuleException { - // Create the table names we use - storageSource.createTable(CONTROLLER_TABLE_NAME, null); - storageSource.createTable(CONTROLLER_INTERFACE_TABLE_NAME, null); - storageSource.createTable(SWITCH_CONFIG_TABLE_NAME, null); - storageSource.setTablePrimaryKeyName(CONTROLLER_TABLE_NAME, - CONTROLLER_ID); - storageSource.addListener(CONTROLLER_INTERFACE_TABLE_NAME, this); - - storageSource.createTable(FLOW_PRIORITY_TABLE_NAME, null); - storageSource.setTablePrimaryKeyName(FLOW_PRIORITY_TABLE_NAME, - FLOW_COLUMN_PRIMARY_KEY); - storageSource.addListener(FLOW_PRIORITY_TABLE_NAME, this); - readFlowPriorityConfigurationFromStorage(); - - // Startup load monitoring - if (overload_drop) { - this.loadmonitor.startMonitoring( - this.threadPool.getScheduledExecutor()); - } - - // Add our REST API - restApi.addRestletRoutable(new CoreWebRoutable()); - - this.ses = threadPool.getScheduledExecutor(); - - try { - this.syncService.registerStore(SWITCH_SYNC_STORE_NAME, Scope.LOCAL); - this.storeClient = this.syncService - .getStoreClient(SWITCH_SYNC_STORE_NAME, - Long.class, - SwitchSyncRepresentation.class); - this.storeClient.addStoreListener(this.switchManager); - } catch (SyncException e) { - throw new FloodlightModuleException("Error while setting up sync service", e); - } - - try { - this.counters.createCounters(debugCounters); - } catch (CounterException e) { - throw new FloodlightModuleException(e.getMessage()); - } - - addInfoProvider("summary", this); - - registerControllerDebugEvents(); - } - - @LogMessageDoc(level="ERROR", - message="failed to access storage: {reason}", - explanation="Could not retrieve forwarding configuration", - recommendation=LogMessageDoc.CHECK_CONTROLLER) - private void readFlowPriorityConfigurationFromStorage() { - try { - Map<String, Object> row; - IResultSet resultSet = storageSource.executeQuery( - FLOW_PRIORITY_TABLE_NAME, FLOW_COLUMN_NAMES, null, null); - if (resultSet == null) - return; - - for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) { - row = it.next().getRow(); - if (row.containsKey(FLOW_COLUMN_PRIMARY_KEY)) { - String primary_key = (String) row.get(FLOW_COLUMN_PRIMARY_KEY); - if (primary_key.equals(FLOW_VALUE_PRIMARY_KEY)) { - if (row.containsKey(FLOW_COLUMN_ACCESS_PRIORITY)) { - accessPriority = - Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY)); - } - if (row.containsKey(FLOW_COLUMN_CORE_PRIORITY)) { - corePriority = - Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY)); - } - } - } - } - } - catch (StorageException e) { - log.error("Failed to access storage for forwarding configuration: {}", - e.getMessage()); - } - catch (NumberFormatException e) { - // log error, no stack-trace - log.error("Failed to read core or access flow priority from " + - "storage. Illegal number: {}", e.getMessage()); - } - } - - - private void registerControllerDebugEvents() throws FloodlightModuleException { - if (debugEvents == null) { - debugEvents = new NullDebugEvent(); - } - try { - evSwitch = debugEvents.registerEvent( - Counters.prefix, "switchevent", - "Switch connected, disconnected or port changed", - EventType.ALWAYS_LOG, SwitchEvent.class, 100); - } catch (MaxEventsRegistered e) { - throw new FloodlightModuleException("Max events registered", e); - } - } - - public class SwitchEvent { - @EventColumn(name = "dpid", description = EventFieldType.DPID) - long dpid; - - @EventColumn(name = "reason", description = EventFieldType.STRING) - String reason; - - public SwitchEvent(long dpid, String reason) { - this.dpid = dpid; - this.reason = reason; - } - } - - @Override - public void addInfoProvider(String type, IInfoProvider provider) { - if (!providerMap.containsKey(type)) { - providerMap.put(type, new ArrayList<IInfoProvider>()); - } - providerMap.get(type).add(provider); - } - - @Override - public void removeInfoProvider(String type, IInfoProvider provider) { - if (!providerMap.containsKey(type)) { - log.debug("Provider type {} doesn't exist.", type); - return; - } - - providerMap.get(type).remove(provider); - } - - @Override - public Map<String, Object> getControllerInfo(String type) { - if (!providerMap.containsKey(type)) return null; - - Map<String, Object> result = new LinkedHashMap<String, Object>(); - for (IInfoProvider provider : providerMap.get(type)) { - result.putAll(provider.getInfo(type)); - } - - return result; - } - - @Override - public void addHAListener(IHAListener listener) { - this.haListeners.addListener(null,listener); - } - - @Override - public void removeHAListener(IHAListener listener) { - this.haListeners.removeListener(listener); - } - - @Override - public void addReadyForReconcileListener(IReadyForReconcileListener l) { - this.readyForReconcileListeners.add(l); - } - - - /** - * Handle changes to the controller nodes IPs and dispatch update. - */ - protected void handleControllerNodeIPChanges() { - HashMap<String,String> curControllerNodeIPs = new HashMap<String,String>(); - HashMap<String,String> addedControllerNodeIPs = new HashMap<String,String>(); - HashMap<String,String> removedControllerNodeIPs =new HashMap<String,String>(); - String[] colNames = { CONTROLLER_INTERFACE_CONTROLLER_ID, - CONTROLLER_INTERFACE_TYPE, - CONTROLLER_INTERFACE_NUMBER, - CONTROLLER_INTERFACE_DISCOVERED_IP }; - synchronized(controllerNodeIPsCache) { - // We currently assume that interface Ethernet0 is the relevant - // controller interface. Might change. - // We could (should?) implement this using - // predicates, but creating the individual and compound predicate - // seems more overhead then just checking every row. Particularly, - // since the number of rows is small and changes infrequent - IResultSet res = storageSource.executeQuery(CONTROLLER_INTERFACE_TABLE_NAME, - colNames,null, null); - while (res.next()) { - if (res.getString(CONTROLLER_INTERFACE_TYPE).equals("Ethernet") && - res.getInt(CONTROLLER_INTERFACE_NUMBER) == 0) { - String controllerID = res.getString(CONTROLLER_INTERFACE_CONTROLLER_ID); - String discoveredIP = res.getString(CONTROLLER_INTERFACE_DISCOVERED_IP); - String curIP = controllerNodeIPsCache.get(controllerID); - - curControllerNodeIPs.put(controllerID, discoveredIP); - if (curIP == null) { - // new controller node IP - addedControllerNodeIPs.put(controllerID, discoveredIP); - } - else if (!curIP.equals(discoveredIP)) { - // IP changed - removedControllerNodeIPs.put(controllerID, curIP); - addedControllerNodeIPs.put(controllerID, discoveredIP); - } - } - } - // Now figure out if rows have been deleted. We can't use the - // rowKeys from rowsDeleted directly, since the tables primary - // key is a compound that we can't disassemble - Set<String> curEntries = curControllerNodeIPs.keySet(); - Set<String> removedEntries = controllerNodeIPsCache.keySet(); - removedEntries.removeAll(curEntries); - for (String removedControllerID : removedEntries) - removedControllerNodeIPs.put(removedControllerID, - controllerNodeIPsCache.get(removedControllerID)); - controllerNodeIPsCache.clear(); - controllerNodeIPsCache.putAll(curControllerNodeIPs); - counters.controllerNodeIpsChanged.updateCounterWithFlush(); - HAControllerNodeIPUpdate update = new HAControllerNodeIPUpdate( - curControllerNodeIPs, addedControllerNodeIPs, - removedControllerNodeIPs); - if (!removedControllerNodeIPs.isEmpty() || !addedControllerNodeIPs.isEmpty()) { - addUpdateToQueue(update); - } - } - } - - @Override - public Map<String, String> getControllerNodeIPs() { - // We return a copy of the mapping so we can guarantee that - // the mapping return is the same as one that will be (or was) - // dispatched to IHAListeners - HashMap<String,String> retval = new HashMap<String,String>(); - synchronized(controllerNodeIPsCache) { - retval.putAll(controllerNodeIPsCache); - } - return retval; - } - - private static final String FLOW_PRIORITY_CHANGED_AFTER_STARTUP = - "Flow priority configuration has changed after " + - "controller startup. Restart controller for new " + - "configuration to take effect."; - @LogMessageDoc(level="WARN", - message=FLOW_PRIORITY_CHANGED_AFTER_STARTUP, - explanation="A user has changed the priority with which access " + - "and core flows are installed after controller startup. " + - "Changing this setting will only take affect after a " + - "controller restart", - recommendation="Restart controller") - @Override - public void rowsModified(String tableName, Set<Object> rowKeys) { - if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) { - handleControllerNodeIPChanges(); - } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) { - log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP); - } - - - } - - @Override - public void rowsDeleted(String tableName, Set<Object> rowKeys) { - if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) { - handleControllerNodeIPChanges(); - } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) { - log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP); - } - } - - @Override - public long getSystemStartTime() { - RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); - return rb.getStartTime(); - } - - @Override - public void setAlwaysClearFlowsOnSwActivate(boolean value) { - this.alwaysClearFlowsOnSwActivate = value; - } - - - @Override - public Map<String, Long> getMemory() { - Map<String, Long> m = new HashMap<String, Long>(); - Runtime runtime = Runtime.getRuntime(); - m.put("total", runtime.totalMemory()); - m.put("free", runtime.freeMemory()); - return m; - } - - @Override - public Long getUptime() { - RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean(); - return rb.getUptime(); - } - - - - @Override - public void addOFSwitchDriver(String manufacturerDescriptionPrefix, - IOFSwitchDriver driver) { - driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver); - } - - /** - * Forward to the registry to get an IOFSwitch instance. - * @param desc - * @return - */ - IOFSwitch getOFSwitchInstance(OFDescriptionStatistics desc) { - return driverRegistry.getOFSwitchInstance(desc); - } - - /** - * Switch Added/Deleted Events - */ - @Override - public void addSwitchEvent(long switchDPID, String reason, boolean flushNow) { - switchManager.addSwitchEvent(switchDPID, reason, flushNow); - } - - @LogMessageDoc(level="WARN", - message="Failure adding update {} to queue", - explanation="The controller tried to add an internal notification" + - " to its message queue but the add failed.", - recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) - private void addUpdateToQueue(IUpdate update) { - try { - this.updates.put(update); - } catch (InterruptedException e) { - // This should never happen - log.error("Failure adding update {} to queue.", update); - } - } - - void flushAll() { - // Flush all flow-mods/packet-out/stats generated from this "train" - OFSwitchBase.flush_all(); - counterStore.updateFlush(); - debugCounters.flushCounters(); - debugEvents.flushEvents(); - } - - short getAccessFlowPriority() { - return accessPriority; - } - - short getCoreFlowPriority() { - return corePriority; - } - - /** - * FOR TESTING ONLY. - * Dispatch all updates in the update queue until queue is empty - */ - void processUpdateQueueForTesting() { - while(!updates.isEmpty()) { - IUpdate update = updates.poll(); - if (update != null) - update.dispatch(); - } - } - - /** - * FOR TESTING ONLY - * check if update queue is empty - */ - boolean isUpdateQueueEmptyForTesting() { - return this.updates.isEmpty(); - } - - /** - * FOR TESTING ONLY - * @param update - */ - void setConsolidateStoreTaskDelay(int consolidateStoreTaskDelayMs) { - this.consolidateStoreTimeDelayMs = consolidateStoreTaskDelayMs; - } - - /** - * FOR TESTING ONLY - * returns the store listener so we can send events to the listener - */ - IStoreListener<Long> getStoreListener() { - return this.switchManager; - } - - @Override - public Map<String, Object> getInfo(String type) { - if (!"summary".equals(type)) return null; - - Map<String, Object> info = new HashMap<String, Object>(); - - info.put("# Switches", this.getAllSwitchDpids().size()); - return info; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java new file mode 100644 index 0000000000000000000000000000000000000000..c511a09ee13d9d6604cbc3e9c095adea8d6c0b8b --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java @@ -0,0 +1,48 @@ +package net.floodlightcontroller.core.internal; + +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.OFConnectionCounters; +import net.floodlightcontroller.debugcounter.IDebugCounter; +import net.floodlightcontroller.debugcounter.IDebugCounterService; +import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", + justification = "It is ok to predefine Debug Counters that are not yet used") +public class ControllerCounters { + + public final String prefix = ControllerCounters.class.getSimpleName(); + public final String statsPrefix = IOFSwitchBackend.class.getPackage() + .getName(); + + public final IDebugCounter packetParsingError; + public final IDebugCounter dispatchMessageWhileStandby; + public final IDebugCounter dispatchMessage; + + public ControllerCounters(IDebugCounterService debugCounters) { + debugCounters.registerModule(prefix); + debugCounters.registerModule(OFConnectionCounters.COUNTER_MODULE); + + dispatchMessageWhileStandby = debugCounters.registerCounter(prefix, + "dispatch-message-while-slave", + "Number of times an OF message was received " + + "and supposed to be dispatched but the " + + "controller was in SLAVE role and the message " + + "was not dispatched"); + // does this cnt make sense? more specific?? per type? + // count stops? + dispatchMessage = debugCounters.registerCounter(prefix, + "dispatch-message", + "Number of times an OF message was dispatched " + + "to registered modules"); + + // TODO: FIXME + // Need a better way to handle these + packetParsingError = debugCounters.registerCounter(prefix, + "packet-parsing-error", + "Number of times the packet parsing " + + "encountered an error", + MetaData.ERROR); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java index 8299bb2c223f6c93437813db9dc8963acf386859..12716c4bab5c4b4afeb55089a5ee7264e2d46148 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java +++ b/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java @@ -21,6 +21,11 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import net.floodlightcontroller.core.internal.IOFSwitchService; +import net.floodlightcontroller.core.internal.Controller; +import net.floodlightcontroller.core.module.Run; + +import org.projectfloodlight.openflow.protocol.OFType; import org.sdnplatform.sync.ISyncService; import net.floodlightcontroller.core.IFloodlightProviderService; @@ -39,6 +44,10 @@ import net.floodlightcontroller.threadpool.IThreadPoolService; public class FloodlightProvider implements IFloodlightModule { Controller controller; + public FloodlightProvider() { + controller = new Controller(); + } + @Override public Collection<Class<? extends IFloodlightService>> getModuleServices() { Collection<Class<? extends IFloodlightService>> services = @@ -70,6 +79,7 @@ public class FloodlightProvider implements IFloodlightModule { dependencies.add(ICounterStoreService.class); dependencies.add(IDebugCounterService.class); dependencies.add(IDebugEventService.class); + dependencies.add(IOFSwitchService.class); dependencies.add(IThreadPoolService.class); dependencies.add(ISyncService.class); return dependencies; @@ -99,6 +109,23 @@ public class FloodlightProvider implements IFloodlightModule { @Override public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { - controller.startupComponents(); + controller.startupComponents(context.getModuleLoader()); } + + @Run(mainLoop=true) + public void run() throws FloodlightModuleException { + controller.run(); + } + + @Override + public boolean isCallbackOrderingPrereq(OFType type, String name) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isCallbackOrderingPostreq(OFType type, String name) { + // TODO Auto-generated method stub + return false; + } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java b/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java index e89b3895c7e77ff7fde72e83e61aad25e1598fe1..89ef68109bdc715eb2c16ea3f59f6c2c7b33fc67 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java +++ b/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java @@ -1,7 +1,7 @@ /** -* Copyright 2011, Big Switch Networks, Inc. +* Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University -* +* * 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 @@ -30,36 +30,37 @@ import org.jboss.netty.util.TimerTask; /** * Trigger a timeout if a switch fails to complete handshake soon enough */ -public class HandshakeTimeoutHandler +public class HandshakeTimeoutHandler extends SimpleChannelUpstreamHandler { - static final HandshakeTimeoutException EXCEPTION = + + static final HandshakeTimeoutException EXCEPTION = new HandshakeTimeoutException(); - - final OFChannelHandler channelHandler; + + final OFChannelHandler handshakeHandler; final Timer timer; final long timeoutNanos; volatile Timeout timeout; - - public HandshakeTimeoutHandler(OFChannelHandler channelHandler, + + public HandshakeTimeoutHandler(OFChannelHandler handshakeHandler, Timer timer, long timeoutSeconds) { super(); - this.channelHandler = channelHandler; + this.handshakeHandler = handshakeHandler; this.timer = timer; this.timeoutNanos = TimeUnit.SECONDS.toNanos(timeoutSeconds); } - + @Override public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { if (timeoutNanos > 0) { - timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx), + timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx), timeoutNanos, TimeUnit.NANOSECONDS); } ctx.sendUpstream(e); } - + @Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { @@ -68,7 +69,7 @@ public class HandshakeTimeoutHandler timeout = null; } } - + private final class HandshakeTimeoutTask implements TimerTask { private final ChannelHandlerContext ctx; @@ -86,7 +87,7 @@ public class HandshakeTimeoutHandler if (!ctx.getChannel().isOpen()) { return; } - if (!channelHandler.isHandshakeComplete()) + if (!handshakeHandler.isSwitchHandshakeComplete()) Channels.fireExceptionCaught(ctx, EXCEPTION); } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java b/src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..fd45309f30208a9b965de54fa92c7b1e4f5859e2 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java @@ -0,0 +1,19 @@ +package net.floodlightcontroller.core.internal; + +/** + * This interface creates a contract used by the switch handshake handler. Each + * switch that is connected needs it's own running instance of the registered + * plugins. Thus is depends on a factory to churn out these instances. + * @author Jason Parraga <Jason.Parraga@bigswitch.com> + * + */ +public interface IAppHandshakePluginFactory { + + /** + * Create an instance of OFSwitchAppHandshakePlugin + * @return an instance of OFSwitchAppHandshakePlugin + */ + OFSwitchAppHandshakePlugin createPlugin(); +} + + diff --git a/src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java b/src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java new file mode 100644 index 0000000000000000000000000000000000000000..9f03bc38e422bb3da8623b5e8bf2eddf245d7d90 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java @@ -0,0 +1,19 @@ +package net.floodlightcontroller.core.internal; + +import net.floodlightcontroller.core.IOFConnectionBackend; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; + +/** a listener that is notified when a new OFConnection has been opened and + * handshaked (i.e., the {@link OFFeaturesReply} has been received. + * + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public interface INewOFConnectionListener { + /** notify this listener that a new connection has been opened + * + * @param connection - the new connection + * @param featuresReply - the {@link OFFeaturesReply} that was received. + */ + void connectionOpened(IOFConnectionBackend connection, + OFFeaturesReply featuresReply); +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java b/src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java new file mode 100644 index 0000000000000000000000000000000000000000..f537e2d4fff00de8405346326f91fff9a93cba42 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java @@ -0,0 +1,12 @@ +package net.floodlightcontroller.core.internal; + +import net.floodlightcontroller.core.IOFConnectionBackend; +import org.projectfloodlight.openflow.protocol.OFMessage; + +public interface IOFConnectionListener { + void connectionClosed(IOFConnectionBackend connection); + + void messageReceived(IOFConnectionBackend connection, OFMessage m); + + boolean isSwitchHandshakeComplete(IOFConnectionBackend connection); +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java new file mode 100644 index 0000000000000000000000000000000000000000..81a85346ca78e944cf2cf6dd4d52d6fb7d74ee16 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java @@ -0,0 +1,124 @@ +package net.floodlightcontroller.core.internal; + +import java.util.List; + +import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFSwitch.SwitchStatus; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.IOFSwitchDriver; +import net.floodlightcontroller.core.LogicalOFMessageCategory; +import net.floodlightcontroller.core.PortChangeType; +import net.floodlightcontroller.core.SwitchDescription; + +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.types.DatapathId; + +import com.google.common.collect.ImmutableList; + +public interface IOFSwitchManager { + + /** + * Called when a switch is added. + * @param sw the added switch + */ + void switchAdded(IOFSwitchBackend sw); + + /** + * Called when a switch disconnects + * @param sw the added switch + */ + void switchDisconnected(IOFSwitchBackend sw); + + /** + * Indicates that ports on the given switch have changed. Enqueue a + * switch update. + * @param sw the added switch + */ + void notifyPortChanged(IOFSwitchBackend sw, OFPortDesc port, + PortChangeType type); + + /** + * Relays to ISwitchDriverRegistry + */ + IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, + SwitchDescription description, + OFFactory factory, + DatapathId datapathId); + + /** + * Relays an upstream message to the controller to dispatch to listeners. + * @param sw The switch the message was received on. + * @param m The message received. + * @param bContext the Floodlight context of the message, normally null in this case. + */ + void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext); + + /** + * Gets an unmodifiable collection of OFSwitchHandshakeHandlers + * @return an unmodifiable collection of OFSwitchHandshakeHandlers + */ + ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers(); + + /** + * Adds an OFSwitch driver + * @param manufacturerDescriptionPrefix Register the given prefix + * with the driver. + * @param driver A IOFSwitchDriver instance to handle IOFSwitch instantiation + * for the given manufacturer description prefix + * @throws IllegalStateException If the the manufacturer description is + * already registered + * @throws NullPointerExeption if manufacturerDescriptionPrefix is null + * @throws NullPointerExeption if driver is null + */ + void addOFSwitchDriver(String manufacturerDescriptionPrefix, + IOFSwitchDriver driver); + + /** + * Handles all changes to the switch status. Will alert listeners and manage + * the internal switch map appropriately. + * @param sw the switch that has changed + * @param oldStatus the switch's old status + * @param newStatus the switch's new status + */ + void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, + SwitchStatus newStatus); + + /** + * Gets the number of connections required by the application + * @return the number of connections required by the applications + */ + int getNumRequiredConnections(); + + /** + * Record a switch event in in-memory debug-event + * @param switchDpid + * @param reason Reason for this event + * @param flushNow see debug-event flushing in IDebugEventService + */ + public void addSwitchEvent(DatapathId switchDpid, String reason, boolean flushNow); + + /** + * Get the list of handshake plugins necessary for the switch handshake. + * @return the list of handshake plugins registered by applications. + */ + List<IAppHandshakePluginFactory> getHandshakePlugins(); + + /** + * Get the switch manager's counters + * @return the switch manager's counters + */ + SwitchManagerCounters getCounters(); + + /** + * Checks to see if the supplied category has been registered with the controller + * @param category the logical OF Message category to check or + * @return true if registered + */ + boolean isCategoryRegistered(LogicalOFMessageCategory category); + + void handshakeDisconnected(DatapathId dpid); + +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java new file mode 100644 index 0000000000000000000000000000000000000000..1896d27207e2ba176abbf063cc80aac279831e74 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java @@ -0,0 +1,111 @@ +package net.floodlightcontroller.core.internal; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.IOFSwitchListener; +import net.floodlightcontroller.core.LogicalOFMessageCategory; +import net.floodlightcontroller.core.module.IFloodlightService; +import net.floodlightcontroller.core.rest.SwitchRepresentation; +import org.projectfloodlight.openflow.types.DatapathId; + +public interface IOFSwitchService extends IFloodlightService { + + /** + * Get's the switch map stored in the switch manager + * @return the map of switches known by the switch manager + */ + Map<DatapathId, IOFSwitch> getAllSwitchMap(); + + /** + * If the switch with the given DPID is known to any controller in the + * cluster, this method returns the associated IOFSwitch instance. As such + * the returned switches not necessarily connected or in master role for + * the local controller. + * + * Multiple calls to this method with the same DPID may return different + * IOFSwitch references. A caller must not store or otherwise rely on + * IOFSwitch references to be constant over the lifecycle of a switch. + * + * @param dpid the dpid of the switch to query + * @return the IOFSwitch instance associated with the dpid, null if no + * switch with the dpid is known to the cluster + */ + IOFSwitch getSwitch(DatapathId dpid); + + /** + * If the switch with the given DPID is known to any controller in the + * cluster, this method returns the associated IOFSwitch instance. As such + * the returned switches not necessarily connected or in master role for + * the local controller. + * + * Multiple calls to this method with the same DPID may return different + * IOFSwitch references. A caller must not store or otherwise rely on + * IOFSwitch references to be constant over the lifecycle of a switch. + * + * @param dpid the dpid of the switch to query + * @return the IOFSwitch instance associated with the dpid, null if no + * switch with the dpid is known to the cluster OR if the switch status + * is not considered visible. + */ + IOFSwitch getActiveSwitch(DatapathId dpid); + + /** + * Add a switch listener + * @param listener The module that wants to listen for events + */ + void addOFSwitchListener(IOFSwitchListener listener); + + /** + * Remove a switch listener + * @param listener The The module that no longer wants to listen for events + */ + void removeOFSwitchListener(IOFSwitchListener listener); + + /** + * Registers a logical OFMessage category to be used by an application + * @param category the logical OFMessage category + */ + void registerLogicalOFMessageCategory(LogicalOFMessageCategory category); + + /** + * Registers an app handshake plugin to be used during switch handshaking. + * @param plugin the app handshake plugin to be used during switch handshaking. + */ + void registerHandshakePlugin(IAppHandshakePluginFactory plugin); + + /** + * Get the REST representations of the active switches. + * @return Representation wrappers of the active switches. + */ + List<SwitchRepresentation> getSwitchRepresentations(); + + /** + * Get the REST representation of a switch. + * @param dpid the dpid of the desired switch representation. + * @return The switch representation. + */ + SwitchRepresentation getSwitchRepresentation(DatapathId dpid); + + /** + * Returns a snapshot of the set DPIDs for all known switches. + * + * The returned set is owned by the caller: the caller can modify it at + * will and changes to the known switches are not reflected in the returned + * set. The caller needs to call getAllSwitchDpids() if an updated + * version is needed. + * + * See {@link #getSwitch(long)} for what "known" switch is. + * @return the set of DPIDs of all known switches + */ + Set<DatapathId> getAllSwitchDpids(); + + /** + * Gets an immutable list of handshake handlers. + * @return an immutable list of handshake handlers. + */ + List<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers(); + +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java deleted file mode 100644 index 6251fd26db9eab73cef4824c28ef20100d3b756f..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.floodlightcontroller.core.internal; - -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.IOFSwitchDriver; - -import org.openflow.protocol.statistics.OFDescriptionStatistics; - -/** - * Maintain a registry for SwitchDrivers. Drivers can register with the - * registry and a user can get IOFSwitch instances based on the switch's - * OFDescriptionStatistics. - * - * A driver registers itself by specifying a <i>prefix string</i> of the - * switch's <i>manufacturer</i> description. When a user request an - * IOFSwitch instance the registry matches the manufacturer description - * of the switch against the prefixes in the registry. - * - * See getOFSwitchInstance() for a description of the lookup contract - * - * @author gregor - * - */ -public interface ISwitchDriverRegistry { - - /** - * Register an IOFSwitchDriver with the registry - * - * @param manufacturerDescriptionPrefix Register the given prefix - * with the driver. - * @param driver A IOFSwitchDriver instance to handle IOFSwitch instaniation - * for the given manufacturer description prefix - * @throws IllegalStateException If the the manufacturer description is - * already registered - * @throws NullPointerExeption if manufacturerDescriptionPrefix is null - * @throws NullPointerExeption if driver is null - */ - void addSwitchDriver(String manufacturerDescriptionPrefix, - IOFSwitchDriver driver); - /** - * Return an IOFSwitch instance according to the description stats. - * - * The driver with the <i>longest matching prefix</i> will be picked first. - * The description is then handed over to the choosen driver to return an - * IOFSwitch instance. If the driver does not return an IOFSwitch - * (returns null) the registry will continue to the next driver with - * a matching manufacturer description prefix. If no driver returns an - * IOFSwitch instance the registry returns a default OFSwitchImpl instance. - * - * The returned switch will have its description reply and - * switch properties set according to the DescriptionStats passed in - * - * @param description The OFDescriptionStatistics for which to return an - * IOFSwitch implementation - * @return A IOFSwitch implementation matching the description or an - * OFSwitchImpl if no driver returned a more concrete instance. - * @throws NullPointerException If the OFDescriptionStatistics or any - * of its members is null. - */ - IOFSwitch getOFSwitchInstance(OFDescriptionStatistics description); -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java deleted file mode 100644 index 8109e3add7ebc6f580596eccac975e14b3bf7c6c..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java +++ /dev/null @@ -1,105 +0,0 @@ -package net.floodlightcontroller.core.internal; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; - -import org.openflow.protocol.statistics.OFDescriptionStatistics; - -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.IOFSwitchDriver; - -/** - * This implementation of ISwitchDriverRegistry uses a naiive algorithm to - * perform longest prefix matching on the manufacturere description prefixes - * - * We maintain a map that maps prefixes to the drivers as well as a sorted - * set that contains the prefixes sorted by their length. We exploit the fact - * that lexicographical order defines that shorter strings are always less - * than longer strings with the same prefix). Thus we can use reverse order for - * our purposes. - * To perform a lookup we iterate through the sorted set until we find a prefix - * that matches the manufacturer description. Since the set is sorted this - * will be the longest matching prefix. - * - * @author gregor - */ -class NaiiveSwitchDriverRegistry implements ISwitchDriverRegistry { - private final SortedSet<String> switchDescSorted; - private final Map<String,IOFSwitchDriver> switchBindingMap; - - public NaiiveSwitchDriverRegistry() { - switchBindingMap = new HashMap<String, IOFSwitchDriver>(); - switchDescSorted = new TreeSet<String>(Collections.reverseOrder()); - } - - @Override - public synchronized void addSwitchDriver(String manufacturerDescPrefix, - IOFSwitchDriver driver) { - if (manufacturerDescPrefix == null) { - throw new NullPointerException("manufacturerDescrptionPrefix" + - " must not be null"); - } - if (driver == null) { - throw new NullPointerException("driver must not be null"); - } - - IOFSwitchDriver existingDriver = switchBindingMap.get(manufacturerDescPrefix); - if (existingDriver != null ) { - throw new IllegalStateException("Failed to add OFSwitch driver for " - + manufacturerDescPrefix + "already registered"); - } - switchBindingMap.put(manufacturerDescPrefix, driver); - switchDescSorted.add(manufacturerDescPrefix); - } - - @Override - // TODO: instead of synchronized we could actually use a r/w lock - // but it's probably not worth it. - public synchronized IOFSwitch - getOFSwitchInstance(OFDescriptionStatistics description) { - if (description == null) - throw new NullPointerException("description must not be null"); - if (description.getHardwareDescription() == null) { - throw new NullPointerException( - "hardware description must not be null"); - } - if (description.getManufacturerDescription() == null) { - throw new NullPointerException( - "manufacturer description must not be null"); - } - if (description.getSerialNumber() == null) { - throw new NullPointerException( - "serial number must not be null"); - } - if (description.getDatapathDescription() == null) { - throw new NullPointerException( - "datapath description must not be null"); - } - if (description.getSoftwareDescription() == null) { - throw new NullPointerException( - "software description must not be null"); - } - - - // Find the appropriate driver - for (String descPrefix: switchDescSorted) { - if (description.getManufacturerDescription() - .startsWith(descPrefix)) { - IOFSwitchDriver driver = switchBindingMap.get(descPrefix); - IOFSwitch sw = driver.getOFSwitchImpl(description); - if (sw != null) { - sw.setSwitchProperties(description); - return sw; - } - } - } - // no switch found - IOFSwitch sw = new OFSwitchImpl(); - sw.setSwitchProperties(description); - return sw; - } - -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..6f2fffed183dd3e58ab59729a5f8d636ad3a9009 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java @@ -0,0 +1,102 @@ +package net.floodlightcontroller.core.internal; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.annotation.Nonnull; + +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.IOFSwitchDriver; +import net.floodlightcontroller.core.OFSwitch; +import net.floodlightcontroller.core.SwitchDescription; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.types.DatapathId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; + +/** + * This implementation of ISwitchDriverRegistry uses a naive algorithm to + * perform longest prefix matching on the manufacturer description prefixes + * + * We maintain a map that maps prefixes to the drivers as well as a sorted + * set that contains the prefixes sorted by their length. We exploit the fact + * that lexicographical order defines that shorter strings are always less + * than longer strings with the same prefix). Thus we can use reverse order for + * our purposes. + * To perform a lookup we iterate through the sorted set until we find a prefix + * that matches the manufacturer description. Since the set is sorted this + * will be the longest matching prefix. + * + * @author gregor + */ +class NaiveSwitchDriverRegistry implements ISwitchDriverRegistry { + + protected static final Logger log = LoggerFactory.getLogger(NaiveSwitchDriverRegistry.class); + private final SortedSet<String> switchDescSorted; + private final Map<String,IOFSwitchDriver> switchBindingMap; + private final IOFSwitchManager switchManager; + + public NaiveSwitchDriverRegistry(@Nonnull IOFSwitchManager switchManager) { + Preconditions.checkNotNull(switchManager, "switchManager must not be null"); + this.switchManager = switchManager; + switchBindingMap = new HashMap<String, IOFSwitchDriver>(); + switchDescSorted = new TreeSet<String>(Collections.reverseOrder()); + } + + @Override + public synchronized void addSwitchDriver(@Nonnull String manufacturerDescPrefix, + @Nonnull IOFSwitchDriver driver) { + Preconditions.checkNotNull(manufacturerDescPrefix, "manufactererDescProfix"); + Preconditions.checkNotNull(driver, "driver"); + + IOFSwitchDriver existingDriver = switchBindingMap.get(manufacturerDescPrefix); + if (existingDriver != null ) { + throw new IllegalStateException("Failed to add OFSwitch driver for " + + manufacturerDescPrefix + "already registered"); + } + switchBindingMap.put(manufacturerDescPrefix, driver); + switchDescSorted.add(manufacturerDescPrefix); + } + + @Override + // TODO: instead of synchronized we could actually use a r/w lock + // but it's probably not worth it. + public synchronized IOFSwitchBackend + getOFSwitchInstance(@Nonnull IOFConnectionBackend connection, @Nonnull SwitchDescription description, + @Nonnull OFFactory factory, @Nonnull DatapathId id) { + Preconditions.checkNotNull(connection, "connection"); + Preconditions.checkNotNull(description, "description"); + Preconditions.checkNotNull(factory, "factory"); + Preconditions.checkNotNull(id, "id"); + + Preconditions.checkNotNull(description.getHardwareDescription(), "hardware description"); + Preconditions.checkNotNull(description.getManufacturerDescription(), "manufacturer description"); + Preconditions.checkNotNull(description.getSerialNumber(), "serial number"); + Preconditions.checkNotNull(description.getDatapathDescription(), "datapath description"); + Preconditions.checkNotNull(description.getSoftwareDescription(), "software description"); + + // Find the appropriate driver + for (String descPrefix: switchDescSorted) { + if (description.getManufacturerDescription() + .startsWith(descPrefix)) { + IOFSwitchDriver driver = switchBindingMap.get(descPrefix); + IOFSwitchBackend sw = driver.getOFSwitchImpl(description, factory); + if (sw != null) { + sw.setSwitchProperties(description); + return sw; + } + } + } + // no switch found + IOFSwitchBackend sw = new OFSwitch(connection, factory, switchManager, id); + sw.setSwitchProperties(description); + return sw; + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java b/src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..bf84d89a9047bf4bdc91bb635e6aecd11d0cbf69 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java @@ -0,0 +1,40 @@ +package net.floodlightcontroller.core.internal; + +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole; +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply; + +/** static utilities to convert between Pre-OF1.2 "Nicira Style" roles and OF1.2+ OpenFlow + * standard roles. + * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> + */ +public class NiciraRoleUtils { + private NiciraRoleUtils() {} + + public static OFControllerRole niciraToOFRole(OFNiciraControllerRoleReply roleReply) { + switch(roleReply.getRole()) { + case ROLE_MASTER: + return OFControllerRole.ROLE_MASTER; + case ROLE_OTHER: + return OFControllerRole.ROLE_EQUAL; + case ROLE_SLAVE: + return OFControllerRole.ROLE_SLAVE; + default: + throw new IllegalArgumentException("unknown Nicira role value: " + roleReply.getRole()); + } + } + + public static OFNiciraControllerRole ofRoleToNiciraRole(OFControllerRole role) { + switch(role) { + case ROLE_EQUAL: + return OFNiciraControllerRole.ROLE_OTHER; + case ROLE_MASTER: + return OFNiciraControllerRole.ROLE_MASTER; + case ROLE_SLAVE: + return OFNiciraControllerRole.ROLE_SLAVE; + default: + throw new IllegalArgumentException("Unknown role: " + role); + } + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutException.java b/src/main/java/net/floodlightcontroller/core/internal/OFAuxException.java similarity index 51% rename from src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutException.java rename to src/main/java/net/floodlightcontroller/core/internal/OFAuxException.java index 421ec1ac7dd3121a245b1b3b82fee0131b86f032..e2a6ccfdd8c0e1a6af30bfe91f4fecea3b6035d5 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutException.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFAuxException.java @@ -1,7 +1,7 @@ /** -* Copyright 2011, Big Switch Networks, Inc. +* Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University -* +* * 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 @@ -18,12 +18,25 @@ package net.floodlightcontroller.core.internal; /** - * Exception is thrown when the handshake fails to complete - * before a specified time - * @author readams + * This exception indicates an error or unexpected message during + * OF Aux handshaking. E.g., if a switch reports that it cannot supply us + * with the number of OF Aux connections needed. + * @author Jason Parraga <Jason.Parraga@bigswitch.com> */ -public class HandshakeTimeoutException extends Exception { +public class OFAuxException extends SwitchStateException{ + + private static final long serialVersionUID = 8452081020837079086L; + + public OFAuxException() { + super(); + } - private static final long serialVersionUID = 6859880268940337312L; + public OFAuxException(String arg0) { + super(arg0); + } -} + public OFAuxException(Throwable arg0) { + super(arg0); + } + +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java deleted file mode 100644 index 76f819ac904d35ceebd619c7c24da8eeae7e0324..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java +++ /dev/null @@ -1,1788 +0,0 @@ -package net.floodlightcontroller.core.internal; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - -import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.IFloodlightProviderService.Role; -import net.floodlightcontroller.core.IOFSwitch.PortChangeEvent; -import net.floodlightcontroller.core.annotations.LogMessageDoc; -import net.floodlightcontroller.core.annotations.LogMessageDocs; -import net.floodlightcontroller.core.internal.Controller.Counters; -import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException; -import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.StorageException; -import net.floodlightcontroller.util.LoadMonitor; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.channel.ChannelStateEvent; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.channel.ExceptionEvent; -import org.jboss.netty.channel.MessageEvent; -import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; -import org.jboss.netty.handler.timeout.IdleStateEvent; -import org.jboss.netty.handler.timeout.ReadTimeoutException; -import org.openflow.protocol.OFBarrierReply; -import org.openflow.protocol.OFBarrierRequest; -import org.openflow.protocol.OFEchoReply; -import org.openflow.protocol.OFEchoRequest; -import org.openflow.protocol.OFError; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFFlowRemoved; -import org.openflow.protocol.OFGetConfigReply; -import org.openflow.protocol.OFGetConfigRequest; -import org.openflow.protocol.OFHello; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPortStatus; -import org.openflow.protocol.OFQueueGetConfigReply; -import org.openflow.protocol.OFSetConfig; -import org.openflow.protocol.OFStatisticsReply; -import org.openflow.protocol.OFStatisticsRequest; -import org.openflow.protocol.OFSwitchConfig; -import org.openflow.protocol.OFType; -import org.openflow.protocol.OFVendor; -import org.openflow.protocol.OFError.OFBadActionCode; -import org.openflow.protocol.OFError.OFBadRequestCode; -import org.openflow.protocol.OFError.OFErrorType; -import org.openflow.protocol.OFError.OFFlowModFailedCode; -import org.openflow.protocol.OFError.OFHelloFailedCode; -import org.openflow.protocol.OFError.OFPortModFailedCode; -import org.openflow.protocol.OFError.OFQueueOpFailedCode; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.MessageParseException; -import org.openflow.protocol.statistics.OFDescriptionStatistics; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.util.HexString; -import org.openflow.vendor.nicira.OFNiciraVendorData; -import org.openflow.vendor.nicira.OFRoleReplyVendorData; -import org.openflow.vendor.nicira.OFRoleRequestVendorData; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.bigswitch.floodlight.vendor.OFBigSwitchVendorData; -import com.bigswitch.floodlight.vendor.OFBsnL2TableSetVendorData; - - - -/** - * Channel handler deals with the switch connection and dispatches - * switch messages to the appropriate locations. - * @author readams - */ -class OFChannelHandler - extends IdleStateAwareChannelHandler { - - private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class); - - private static final long DEFAULT_ROLE_TIMEOUT_MS = 10*1000; // 10 sec - - private final Controller controller; - private final Counters counters; - private IOFSwitch sw; - private Channel channel; - // State needs to be volatile because the HandshakeTimeoutHandler - // needs to check if the handshake is complete - private volatile ChannelState state; - private RoleChanger roleChanger; - private OFFeaturesReply featuresReply; - - private final ArrayList<OFPortStatus> pendingPortStatusMsg; - - /** transaction Ids to use during handshake. Since only one thread - * calls into the OFChannelHandler we don't need atomic. - * We will count down - */ - private int handshakeTransactionIds = -1; - - - - /** - * When we remove a pending role request and set the role on the switch - * we use this enum to indicate how we arrived at the decision. - * @author gregor - */ - private enum RoleRecvStatus { - /** We receveived a role reply message from the switch */ - RECEIVED_REPLY, - /** The switch returned an error indicated that roles are not - * supported*/ - UNSUPPORTED, - /** The request timed out */ - NO_REPLY; - } - /** - * A utility class to handle role requests and replies for this channel. - * After a role request is submitted the role changer keeps track of the - * pending request, collects the reply (if any) and times out the request - * if necessary. - * - * To simplify role handling we only keep track of the /last/ pending - * role reply send to the switch. If multiple requests are pending and - * we receive replies for earlier requests we ignore them. However, this - * way of handling pending requests implies that we could wait forever if - * a new request is submitted before the timeout triggers. If necessary - * we could work around that though. - * @author gregor - */ - private class RoleChanger { - // indicates that a request is currently pending - // needs to be volatile to allow correct double-check idiom - private volatile boolean requestPending; - // the transactiong Id of the pending request - private int pendingXid; - // the role that's pending - private Role pendingRole; - // system time in MS when we send the request - private long roleSubmitTime; - // the timeout to use - private final long roleTimeoutMs; - - public RoleChanger(long roleTimeoutMs) { - this.requestPending = false; - this.roleSubmitTime = 0; - this.pendingXid = -1; - this.pendingRole = null; - this.roleTimeoutMs = roleTimeoutMs; - } - - /** - * Send NX role request message to the switch requesting the specified - * role. - * - * @param sw switch to send the role request message to - * @param role role to request - */ - private int sendNxRoleRequest(Role role) - throws IOException { - - int xid = sw.getNextTransactionId(); - // Convert the role enum to the appropriate integer constant used - // in the NX role request message - int nxRole = role.toNxRole(); - - // Construct the role request message - OFVendor roleRequest = (OFVendor)BasicFactory.getInstance() - .getMessage(OFType.VENDOR); - roleRequest.setXid(xid); - roleRequest.setVendor(OFNiciraVendorData.NX_VENDOR_ID); - OFRoleRequestVendorData roleRequestData = new OFRoleRequestVendorData(); - roleRequestData.setRole(nxRole); - roleRequest.setVendorData(roleRequestData); - roleRequest.setLengthU(OFVendor.MINIMUM_LENGTH + - roleRequestData.getLength()); - - // Send it to the switch - sw.write(Collections.<OFMessage>singletonList(roleRequest), - new FloodlightContext()); - - return xid; - } - - /** - * Send a role request for the given role only if no other role - * request is currently pending. - * @param role The role to send to the switch. - * @throws IOException - */ - synchronized void sendRoleRequestIfNotPending(Role role) - throws IOException { - if (!requestPending) - sendRoleRequest(role); - else - counters.roleNotResentBecauseRolePending.updateCounterWithFlush(); - } - - /** - * Send a role request with the given role to the switch. - * - * Send a role request with the given role to the switch and update - * the pending request and timestamp. - * - * @param role - * @throws IOException - */ - synchronized void sendRoleRequest(Role role) throws IOException { - /* - * There are three cases to consider for SUPPORTS_NX_ROLE: - * - * 1) unset. We have neither received a role reply from the - * switch nor has a request timed out. Send a request. - * 2) TRUE: We've already send a request earlier and received - * a reply. The switch supports role and we should send one. - * 3) FALSE: We have already send a role and received an error. - * The switch does not support roles. Don't send a role request, - * set the switch's role directly. - */ - Boolean supportsNxRole = (Boolean) - sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE); - if ((supportsNxRole != null) && !supportsNxRole) { - setSwitchRole(role, RoleRecvStatus.UNSUPPORTED); - } else { - pendingXid = sendNxRoleRequest(role); - pendingRole = role; - roleSubmitTime = System.currentTimeMillis(); - requestPending = true; - } - } - - /** - * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE. - * - * Check if a request is pending and if the received reply matches the - * the expected pending reply (we check both role and xid) we set - * the role for the switch/channel. - * - * If a request is pending but doesn't match the reply we ignore it. - * - * If no request is pending we disconnect. - * - * @param xid - * @param role - * @throws SwitchStateException if no request is pending - */ - synchronized void deliverRoleReply(int xid, Role role) { - if (!requestPending) { - // Maybe don't disconnect if the role reply we received is - // for the same role we are already in. - String msg = String.format("Switch: [%s], State: [%s], " - + "received unexpected RoleReply[%s]. " - + "No roles are pending", - OFChannelHandler.this.getSwitchInfoString(), - OFChannelHandler.this.state.toString(), - role); - throw new SwitchStateException(msg); - } - - if (pendingXid == xid && pendingRole == role) { - log.debug("Received role reply message from {}, setting role to {}", - getSwitchInfoString(), role); - counters.roleReplyReceived.updateCounterWithFlush(); - setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); - } else { - log.debug("Received stale or unexpected role reply from " + - "switch {} ({}, xid={}). Ignoring. " + - "Waiting for {}, xid={}", - new Object[] { getSwitchInfoString(), role, xid, - pendingRole, pendingXid }); - } - } - - /** - * Called if we receive an error message. If the xid matches the - * pending request we handle it otherwise we ignore it. We also - * set SWITCH_SUPPORTS_NX_ROLE to false. - * - * Note: since we only keep the last pending request we might get - * error messages for earlier role requests that we won't be able - * to handle - * @param xid - * @return true if the error was handled by us, false otherwise - * @throws SwitchStateException if the error was for the pending - * role request but was unexpected - */ - synchronized boolean deliverError(OFError error) { - if (!requestPending) - return false; - - if (pendingXid == error.getXid()) { - boolean isBadRequestError = - (error.getErrorType() == OFError.OFErrorType. - OFPET_BAD_REQUEST.getValue()); - if (isBadRequestError) { - counters.roleReplyErrorUnsupported.updateCounterWithFlush(); - setSwitchRole(pendingRole, RoleRecvStatus.UNSUPPORTED); - } else { - // TODO: Is this the right thing to do if we receive - // some other error besides a bad request error? - // Presumably that means the switch did actually - // understand the role request message, but there - // was some other error from processing the message. - // OF 1.2 specifies a OFPET_ROLE_REQUEST_FAILED - // error code, but it doesn't look like the Nicira - // role request has that. Should check OVS source - // code to see if it's possible for any other errors - // to be returned. - // If we received an error the switch is not - // in the correct role, so we need to disconnect it. - // We could also resend the request but then we need to - // check if there are other pending request in which - // case we shouldn't resend. If we do resend we need - // to make sure that the switch eventually accepts one - // of our requests or disconnect the switch. This feels - // cumbersome. - String msg = String.format("Switch: [%s], State: [%s], " - + "Unexpected error %s in respone to our " - + "role request for %s.", - OFChannelHandler.this.getSwitchInfoString(), - OFChannelHandler.this.state.toString(), - getErrorString(error), - pendingRole); - throw new SwitchStateException(msg); - } - return true; - } - return false; - } - - /** - * Check if a pending role request has timed out. - */ - void checkTimeout() { - if (!requestPending) - return; - synchronized(this) { - if (!requestPending) - return; - long now = System.currentTimeMillis(); - if (now - roleSubmitTime > roleTimeoutMs) { - // timeout triggered. - counters.roleReplyTimeout.updateCounterWithFlush(); - setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY); - } - } - } - - /** - * Set the role for this switch / channel. - * - * If the status indicates that we received a reply we set the role. - * If the status indicates otherwise we disconnect the switch if - * the role is SLAVE. - * - * "Setting a role" means setting the appropriate ChannelState, - * setting the flags on the switch and - * notifying Controller.java about new role of the switch - * - * @param role The role to set. - * @param status How we derived at the decision to set this status. - */ - synchronized private void setSwitchRole(Role role, RoleRecvStatus status) { - requestPending = false; - if (status == RoleRecvStatus.RECEIVED_REPLY) - sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); - else - sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); - sw.setHARole(role); - - if (role != Role.SLAVE) { - OFChannelHandler.this.setState(ChannelState.MASTER); - // TODO: should we really activate the switch again if it's - // already master?? - if (log.isDebugEnabled()) { - log.debug("Switch {} activated. Role is now MASTER", - getSwitchInfoString()); - } - controller.switchActivated(OFChannelHandler.this.sw); - } else { - OFChannelHandler.this.setState(ChannelState.SLAVE); - if (status != RoleRecvStatus.RECEIVED_REPLY) { - if (log.isDebugEnabled()) { - log.debug("Disconnecting switch {}. Doesn't support role" - + "({}) request and controller is now SLAVE", - getSwitchInfoString(), status); - } - // the disconnect will trigger a switch removed to - // controller so no need to signal anything else - sw.disconnectOutputStream(); - } else { - if (log.isDebugEnabled()) { - log.debug("Switch {} is now SLAVE", - getSwitchInfoString()); - } - controller.switchDeactivated(OFChannelHandler.this.sw); - } - } - } - } - - - /** - * The state machine for handling the switch/channel state. - * @author gregor - */ - enum ChannelState { - /** - * Initial state before channel is connected. - */ - INIT(false) { - @Override - void - processOFMessage(OFChannelHandler h, OFMessage m) - throws IOException { - illegalMessageReceived(h, m); - } - - @Override - void processOFError(OFChannelHandler h, OFError m) - throws IOException { - // need to implement since its abstract but it will never - // be called - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - unhandledMessageReceived(h, m); - } - }, - - /** - * We send a HELLO to the switch and wait for a reply. - * Once we receive the reply we send an OFFeaturesRequest and - * a request to clear all FlowMods. - * Next state is WAIT_FEATURES_REPLY - */ - WAIT_HELLO(false) { - @Override - void processOFHello(OFChannelHandler h, OFHello m) - throws IOException { - h.sendHandShakeMessage(OFType.FEATURES_REQUEST); - h.setState(WAIT_FEATURES_REPLY); - } - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - illegalMessageReceived(h, m); - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) - throws IOException { - illegalMessageReceived(h, m); - } - @Override - void processOFError(OFChannelHandler h, OFError m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - unhandledMessageReceived(h, m); - } - }, - - /** - * We are waiting for a features reply message. Once we receive it - * we send a SetConfig request, barrier, and GetConfig request. - * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY - */ - WAIT_FEATURES_REPLY(false) { - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - h.featuresReply = m; - if (m.getTables() > 1) { - log.debug("Have {} table for switch {}", m.getTables(), - h.getSwitchInfoString()); - // likely supports L2 table extensions. Send set - h.sendHandshakeL2TableSet(); - // TODO: no L2 SET reply yet, so fire and forget the set - // table message and move directly to sendHandshakeConfig - h.sendHandshakeSetConfig(); - h.setState(WAIT_CONFIG_REPLY); - //h.setState(WAIT_SET_L2_TABLE_REPLY); - } else { - h.sendHandshakeSetConfig(); - h.setState(WAIT_CONFIG_REPLY); - } - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) - throws IOException { - illegalMessageReceived(h, m); - } - @Override - void processOFError(OFChannelHandler h, OFError m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - unhandledMessageReceived(h, m); - } - }, - - WAIT_SET_L2_TABLE_REPLY(false) { - @Override void processOFVendor(OFChannelHandler h, OFVendor m) - throws IOException { - // TODO: actually parse the response - h.sendHandshakeSetConfig(); - h.setState(WAIT_CONFIG_REPLY); - }; - - @Override - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) { - // do nothing; - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - // TODO: we could re-set the features reply - illegalMessageReceived(h, m); - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) - throws IOException { - illegalMessageReceived(h, m); - } - - @Override - void processOFError(OFChannelHandler h, OFError m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - h.pendingPortStatusMsg.add(m); - } - }, - - /** - * We are waiting for a config reply message. Once we receive it - * we send a DescriptionStatsRequest to the switch. - * Next state: WAIT_DESCRIPTION_STAT_REPLY - */ - WAIT_CONFIG_REPLY(false) { - @Override - @LogMessageDocs({ - @LogMessageDoc(level="WARN", - message="Config Reply from {switch} has " + - "miss length set to {length}", - explanation="The controller requires that the switch " + - "use a miss length of 0xffff for correct " + - "function", - recommendation="Use a different switch to ensure " + - "correct function") - }) - void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m) - throws IOException { - if (m.getMissSendLength() == (short)0xffff) { - log.trace("Config Reply from switch {} confirms " - + "miss length set to 0xffff", - h.getSwitchInfoString()); - } else { - // FIXME: we can't really deal with switches that don't send - // full packets. Shouldn't we drop the connection here? - // FIXME: count?? - log.warn("Config Reply from switch {} has" - + "miss length set to {}", - h.getSwitchInfoString(), - m.getMissSendLength()); - } - h.sendHandshakeDescriptionStatsRequest(); - h.setState(WAIT_DESCRIPTION_STAT_REPLY); - } - - @Override - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) { - // do nothing; - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - // TODO: we could re-set the features reply - illegalMessageReceived(h, m); - } - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) - throws IOException { - illegalMessageReceived(h, m); - } - - @Override - void processOFError(OFChannelHandler h, OFError m) { - if (m.getErrorType() == OFErrorType.OFPET_BAD_REQUEST.getValue() - && m.getErrorCode() == - OFBadRequestCode.OFPBRC_BAD_VENDOR.ordinal()) { - log.debug("Switch {} has multiple tables but does not " + - "support L2 table extension", - h.getSwitchInfoString()); - return; - } - logErrorDisconnect(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - h.pendingPortStatusMsg.add(m); - } - }, - - /** - * We are waiting for a OFDescriptionStat message from teh switch. - * Once we receive any stat message we try to parse it. If it's not - * a description stats message we disconnect. If its the expected - * description stats message, we: - * - use the switch driver to bind the switch and get an IOFSwitch - * instance, setup the switch instance - * - setup the IOFSwitch instance - * - add switch to FloodlightProvider and send the intial role - * request to the switch. - * Next state: WAIT_INITIAL_ROLE - * All following states will have a h.sw instance! - */ - WAIT_DESCRIPTION_STAT_REPLY(false) { - @LogMessageDoc(message="Switch {switch info} bound to class " + - "{switch driver}, description {switch description}", - explanation="The specified switch has been bound to " + - "a switch driver based on the switch description" + - "received from the switch") - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) { - // Read description, if it has been updated - OFDescriptionStatistics description = - new OFDescriptionStatistics(); - ChannelBuffer data = - ChannelBuffers.buffer(description.getLength()); - OFStatistics f = m.getFirstStatistics(); - f.writeTo(data); - description.readFrom(data); - h.sw = h.controller.getOFSwitchInstance(description); - // set switch information - // set features reply and channel first so we a DPID and - // channel info. - h.sw.setFeaturesReply(h.featuresReply); - h.sw.setConnected(true); - h.sw.setChannel(h.channel); - h.sw.setFloodlightProvider(h.controller); - h.sw.setThreadPoolService(h.controller.getThreadPoolService()); - try { - h.sw.setDebugCounterService(h.controller.getDebugCounter()); - } catch (CounterException e) { - h.counters.switchCounterRegistrationFailed - .updateCounterNoFlush(); - log.warn("Could not register counters for switch {} ", - h.getSwitchInfoString(), e); - } - h.sw.setAccessFlowPriority(h.controller.getAccessFlowPriority()); - h.sw.setCoreFlowPriority(h.controller.getCoreFlowPriority()); - for (OFPortStatus ps: h.pendingPortStatusMsg) - handlePortStatusMessage(h, ps, false); - h.pendingPortStatusMsg.clear(); - h.readPropertyFromStorage(); - log.info("Switch {} bound to class {}, writeThrottle={}," + - " description {}", - new Object[] { h.sw, h.sw.getClass(), - h.sw.isWriteThrottleEnabled(), - description }); - h.sw.startDriverHandshake(); - if (h.sw.isDriverHandshakeComplete()) - h.gotoWaitInitialRoleState(); - else - h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE); - } - - @Override - void processOFError(OFChannelHandler h, OFError m) { - logErrorDisconnect(h, m); - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - // TODO: we could re-set the features reply - illegalMessageReceived(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - h.pendingPortStatusMsg.add(m); - } - }, - - WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(false) { - @Override - void processOFError(OFChannelHandler h, OFError m) - throws IOException { - // will never be called. We override processOFMessage - } - - @Override - void processOFMessage(OFChannelHandler h, OFMessage m) - throws IOException { - if (m.getType() == OFType.ECHO_REQUEST) - processOFEchoRequest(h, (OFEchoRequest)m); - else { - // FIXME: other message to handle here? - h.sw.processDriverHandshakeMessage(m); - if (h.sw.isDriverHandshakeComplete()) { - h.gotoWaitInitialRoleState(); - } - } - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - handlePortStatusMessage(h, m, false); - } - }, - - /** - * We are waiting for the intial role reply message (or error - * indication) from the switch. - * Next State: MASTER or SLAVE - */ - WAIT_INITIAL_ROLE(false) { - @Override - void processOFError(OFChannelHandler h, OFError m) { - // role changer will ignore the error if it isn't for it - boolean didHandle = h.roleChanger.deliverError(m); - if (!didHandle) { - logError(h, m); - } - } - - @Override - void processOFVendor(OFChannelHandler h, OFVendor m) - throws IOException { - Role role = extractNiciraRoleReply(h, m); - // If role == null it measn the message wasn't really a - // Nicira role reply. We ignore this case. - if (role != null) - h.roleChanger.deliverRoleReply(m.getXid(), role); - else - unhandledMessageReceived(h, m); - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - // TODO: we could re-set the features reply - illegalMessageReceived(h, m); - } - - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) { - illegalMessageReceived(h, m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - handlePortStatusMessage(h, m, false); - - } - }, - - /** - * The switch is in MASTER role. We enter this state after a role - * reply from the switch is received (or the controller is MASTER - * and the switch doesn't support roles). The handshake is complete at - * this point. We only leave this state if the switch disconnects or - * if we send a role request for SLAVE /and/ receive the role reply for - * SLAVE. - */ - MASTER(true) { - @LogMessageDoc(level="WARN", - message="Received permission error from switch {} while" + - "being master. Reasserting master role.", - explanation="The switch has denied an operation likely " + - "indicating inconsistent controller roles", - recommendation="This situation can occurs transiently during role" + - " changes. If, however, the condition persists or happens" + - " frequently this indicates a role inconsistency. " + - LogMessageDoc.CHECK_CONTROLLER ) - @Override - void processOFError(OFChannelHandler h, OFError m) - throws IOException { - // role changer will ignore the error if it isn't for it - boolean didHandle = h.roleChanger.deliverError(m); - if (didHandle) - return; - if (m.getErrorType() == - OFErrorType.OFPET_BAD_REQUEST.getValue() && - m.getErrorCode() == - OFBadRequestCode.OFPBRC_EPERM.ordinal()) { - // We are the master controller and the switch returned - // a permission error. This is a likely indicator that - // the switch thinks we are slave. Reassert our - // role - // FIXME: this could be really bad during role transitions - // if two controllers are master (even if its only for - // a brief period). We might need to see if these errors - // persist before we reassert - h.counters.epermErrorWhileSwitchIsMaster.updateCounterWithFlush(); - log.warn("Received permission error from switch {} while" + - "being master. Reasserting master role.", - h.getSwitchInfoString()); - h.controller.reassertRole(h, Role.MASTER); - } - else if (m.getErrorType() == - OFErrorType.OFPET_PORT_MOD_FAILED.getValue() && - m.getErrorCode() == - OFFlowModFailedCode.OFPFMFC_ALL_TABLES_FULL.ordinal()) { - h.sw.setTableFull(true); - } - else { - logError(h, m); - } - h.dispatchMessage(m); - } - - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) { - h.sw.deliverStatisticsReply(m); - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - h.sw.setFeaturesReply(m); - h.sw.deliverOFFeaturesReply(m); - } - - @Override - void processOFVendor(OFChannelHandler h, OFVendor m) - throws IOException { - Role role = extractNiciraRoleReply(h, m); - // If role == null it means the message wasn't really a - // Nicira role reply. We ignore just dispatch it to the - // OFMessage listenersa in this case. - if (role != null) - h.roleChanger.deliverRoleReply(m.getXid(), role); - else - h.dispatchMessage(m); - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - handlePortStatusMessage(h, m, true); - } - - @Override - void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException { - h.dispatchMessage(m); - } - - @Override - void processOFFlowRemoved(OFChannelHandler h, - OFFlowRemoved m) throws IOException { - h.dispatchMessage(m); - } - @Override - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) throws IOException{ - h.dispatchMessage(m); - } - }, - - /** - * The switch is in SLAVE role. We enter this state after a role - * reply from the switch is received. The handshake is complete at - * this point. We only leave this state if the switch disconnects or - * if we send a role request for MASTER /and/ receive the role reply for - * MASTER. - * TODO: CURRENTLY, WE DO NOT DISPATCH ANY MESSAGE IN SLAVE. - */ - SLAVE(true) { - @Override - void processOFError(OFChannelHandler h, OFError m) - throws IOException { - // role changer will ignore the error if it isn't for it - boolean didHandle = h.roleChanger.deliverError(m); - if (!didHandle) { - logError(h, m); - } - } - - - - @Override - void processOFStatisticsReply(OFChannelHandler h, - OFStatisticsReply m) { - // FIXME. - h.sw.deliverStatisticsReply(m); - } - - @Override - void processOFVendor(OFChannelHandler h, OFVendor m) - throws IOException { - Role role = extractNiciraRoleReply(h, m); - // If role == null it means the message wasn't really a - // Nicira role reply. We ignore it. - if (role != null) - h.roleChanger.deliverRoleReply(m.getXid(), role); - else - unhandledMessageReceived(h, m); - } - - @Override - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - // do nothing - } - - @Override - void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException { - // do nothing - } - - @Override - @LogMessageDoc(level="WARN", - message="Received PacketIn from switch {} while" + - "being slave. Reasserting slave role.", - explanation="The switch has receive a PacketIn despite being " + - "in slave role indicating inconsistent controller roles", - recommendation="This situation can occurs transiently during role" + - " changes. If, however, the condition persists or happens" + - " frequently this indicates a role inconsistency. " + - LogMessageDoc.CHECK_CONTROLLER ) - void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException { - // we don't expect packetIn while slave, reassert we are slave - h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush(); - log.warn("Received PacketIn from switch {} while" + - "being slave. Reasserting slave role.", h.sw); - h.controller.reassertRole(h, Role.SLAVE); - } - }; - - private final boolean handshakeComplete; - ChannelState(boolean handshakeComplete) { - this.handshakeComplete = handshakeComplete; - } - - /** - * Is this a state in which the handshake has completed? - * @return true if the handshake is complete - */ - public boolean isHandshakeComplete() { - return handshakeComplete; - } - - /** - * Get a string specifying the switch connection, state, and - * message received. To be used as message for SwitchStateException - * or log messages - * @param h The channel handler (to get switch information_ - * @param m The OFMessage that has just been received - * @param details A string giving more details about the exact nature - * of the problem. - * @return - */ - // needs to be protected because enum members are acutally subclasses - protected String getSwitchStateMessage(OFChannelHandler h, - OFMessage m, - String details) { - return String.format("Switch: [%s], State: [%s], received: [%s]" - + ", details: %s", - h.getSwitchInfoString(), - this.toString(), - m.getType().toString(), - details); - } - - /** - * We have an OFMessage we didn't expect given the current state and - * we want to treat this as an error. - * We currently throw an exception that will terminate the connection - * However, we could be more forgiving - * @param h the channel handler that received the message - * @param m the message - * @throws SwitchStateExeption we always through the execption - */ - // needs to be protected because enum members are acutally subclasses - protected void illegalMessageReceived(OFChannelHandler h, OFMessage m) { - String msg = getSwitchStateMessage(h, m, - "Switch should never send this message in the current state"); - throw new SwitchStateException(msg); - - } - - /** - * We have an OFMessage we didn't expect given the current state and - * we want to ignore the message - * @param h the channel handler the received the message - * @param m the message - */ - protected void unhandledMessageReceived(OFChannelHandler h, - OFMessage m) { - h.counters.unhandledMessage.updateCounterNoFlush(); - if (log.isDebugEnabled()) { - String msg = getSwitchStateMessage(h, m, - "Ignoring unexpected message"); - log.debug(msg); - } - } - - /** - * Log an OpenFlow error message from a switch - * @param sw The switch that sent the error - * @param error The error message - */ - @LogMessageDoc(level="ERROR", - message="Error {error type} {error code} from {switch} " + - "in state {state}", - explanation="The switch responded with an unexpected error" + - "to an OpenFlow message from the controller", - recommendation="This could indicate improper network operation. " + - "If the problem persists restarting the switch and " + - "controller may help." - ) - protected void logError(OFChannelHandler h, OFError error) { - log.error("{} from switch {} in state {}", - new Object[] { - getErrorString(error), - h.getSwitchInfoString(), - this.toString()}); - } - - /** - * Log an OpenFlow error message from a switch and disconnect the - * channel - * @param sw The switch that sent the error - * @param error The error message - */ - protected void logErrorDisconnect(OFChannelHandler h, OFError error) { - logError(h, error); - h.channel.disconnect(); - } - - - /** - * Extract the role from an OFVendor message. - * - * Extract the role from an OFVendor message if the message is a - * Nicira role reply. Otherwise return null. - * - * @param h The channel handler receiving the message - * @param vendorMessage The vendor message to parse. - * @return The role in the message if the message is a Nicira role - * reply, null otherwise. - * @throws SwitchStateException If the message is a Nicira role reply - * but the numeric role value is unknown. - * FIXME: The message parser should make sure that the Nicira role is - * actually valid. Why do we need to take care of it ?!? - */ - protected Role extractNiciraRoleReply(OFChannelHandler h, - OFVendor vendorMessage) { - int vendor = vendorMessage.getVendor(); - if (vendor != OFNiciraVendorData.NX_VENDOR_ID) - return null; - if (! (vendorMessage.getVendorData() instanceof OFRoleReplyVendorData)) - return null; - OFRoleReplyVendorData roleReplyVendorData = - (OFRoleReplyVendorData) vendorMessage.getVendorData(); - Role role = Role.fromNxRole(roleReplyVendorData.getRole()); - if (role == null) { - String msg = String.format("Switch: [%s], State: [%s], " - + "received NX_ROLE_REPLY with invalid role " - + "value %d", - h.getSwitchInfoString(), - this.toString(), - roleReplyVendorData.getRole()); - throw new SwitchStateException(msg); - } - return role; - } - - /** - * Handle a port status message. - * - * Handle a port status message by updating the port maps in the - * IOFSwitch instance and notifying Controller about the change so - * it can dispatch a switch update. - * - * @param h The OFChannelHhandler that received the message - * @param m The PortStatus message we received - * @param doNotify if true switch port changed events will be - * dispatched - */ - protected void handlePortStatusMessage(OFChannelHandler h, - OFPortStatus m, - boolean doNotify) { - if (h.sw == null) { - String msg = getSwitchStateMessage(h, m, - "State machine error: switch is null. Should never " + - "happen"); - throw new SwitchStateException(msg); - } - Collection<PortChangeEvent> changes = h.sw.processOFPortStatus(m); - if (doNotify) { - for (PortChangeEvent ev: changes) - h.controller.notifyPortChanged(h.sw, ev.port, ev.type); - } - } - - /** - * Process an OF message received on the channel and - * update state accordingly. - * - * The main "event" of the state machine. Process the received message, - * send follow up message if required and update state if required. - * - * Switches on the message type and calls more specific event handlers - * for each individual OF message type. If we receive a message that - * is supposed to be sent from a controller to a switch we throw - * a SwitchStateExeption. - * - * The more specific handlers can also throw SwitchStateExceptions - * - * @param h The OFChannelHandler that received the message - * @param m The message we received. - * @throws SwitchStateException - * @throws IOException - */ - void processOFMessage(OFChannelHandler h, OFMessage m) throws IOException { - h.roleChanger.checkTimeout(); - switch(m.getType()) { - case HELLO: - processOFHello(h, (OFHello)m); - break; - case BARRIER_REPLY: - processOFBarrierReply(h, (OFBarrierReply)m); - break; - case ECHO_REPLY: - processOFEchoReply(h, (OFEchoReply)m); - break; - case ECHO_REQUEST: - processOFEchoRequest(h, (OFEchoRequest)m); - break; - case ERROR: - processOFError(h, (OFError)m); - break; - case FEATURES_REPLY: - processOFFeaturesReply(h, (OFFeaturesReply)m); - break; - case FLOW_REMOVED: - processOFFlowRemoved(h, (OFFlowRemoved)m); - break; - case GET_CONFIG_REPLY: - processOFGetConfigReply(h, (OFGetConfigReply)m); - break; - case PACKET_IN: - processOFPacketIn(h, (OFPacketIn)m); - break; - case PORT_STATUS: - processOFPortStatus(h, (OFPortStatus)m); - break; - case QUEUE_GET_CONFIG_REPLY: - processOFQueueGetConfigReply(h, (OFQueueGetConfigReply)m); - break; - case STATS_REPLY: - processOFStatisticsReply(h, (OFStatisticsReply)m); - break; - case VENDOR: - processOFVendor(h, (OFVendor)m); - break; - // The following messages are sent to switches. The controller - // should never receive them - case SET_CONFIG: - case GET_CONFIG_REQUEST: - case PACKET_OUT: - case PORT_MOD: - case QUEUE_GET_CONFIG_REQUEST: - case BARRIER_REQUEST: - case STATS_REQUEST: - case FEATURES_REQUEST: - case FLOW_MOD: - illegalMessageReceived(h, m); - break; - } - } - - /*----------------------------------------------------------------- - * Default implementation for message handlers in any state. - * - * Individual states must override these if they want a behavior - * that differs from the default. - * - * In general, these handlers simply ignore the message and do - * nothing. - * - * There are some exceptions though, since some messages really - * are handled the same way in every state (e.g., ECHO_REQUST) or - * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY - -----------------------------------------------------------------*/ - - void processOFHello(OFChannelHandler h, OFHello m) throws IOException { - // we only expect hello in the WAIT_HELLO state - illegalMessageReceived(h, m); - } - - void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) - throws IOException { - // Silently ignore. - } - - void processOFEchoRequest(OFChannelHandler h, OFEchoRequest m) - throws IOException { - OFEchoReply reply = (OFEchoReply) - BasicFactory.getInstance().getMessage(OFType.ECHO_REPLY); - reply.setXid(m.getXid()); - reply.setPayload(m.getPayload()); - reply.setLengthU(m.getLengthU()); - h.channel.write(Collections.singletonList(reply)); - } - - void processOFEchoReply(OFChannelHandler h, OFEchoReply m) - throws IOException { - // Do nothing with EchoReplies !! - } - - // no default implementation for OFError - // every state must override it - abstract void processOFError(OFChannelHandler h, OFError m) - throws IOException; - - - void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m) - throws IOException { - unhandledMessageReceived(h, m); - } - - void processOFFlowRemoved(OFChannelHandler h, OFFlowRemoved m) - throws IOException { - unhandledMessageReceived(h, m); - } - - void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m) - throws IOException { - // we only expect config replies in the WAIT_CONFIG_REPLY state - // TODO: might use two different strategies depending on whether - // we got a miss length of 64k or not. - illegalMessageReceived(h, m); - } - - void processOFPacketIn(OFChannelHandler h, OFPacketIn m) - throws IOException { - unhandledMessageReceived(h, m); - } - - // bi default implementation. Every state needs to handle it. - abstract void processOFPortStatus(OFChannelHandler h, OFPortStatus m) - throws IOException; - - void processOFQueueGetConfigReply(OFChannelHandler h, - OFQueueGetConfigReply m) - throws IOException { - unhandledMessageReceived(h, m); - } - - void processOFStatisticsReply(OFChannelHandler h, OFStatisticsReply m) - throws IOException { - unhandledMessageReceived(h, m); - } - - void processOFVendor(OFChannelHandler h, OFVendor m) - throws IOException { - // TODO: it might make sense to parse the vendor message here - // into the known vendor messages we support and then call more - // spefic event handlers - unhandledMessageReceived(h, m); - } - } - - - /** - * Create a new unconnecte OFChannelHandler. - * @param controller - */ - OFChannelHandler(Controller controller) { - this.controller = controller; - this.counters = controller.getCounters(); - this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_MS); - this.state = ChannelState.INIT; - this.pendingPortStatusMsg = new ArrayList<OFPortStatus>(); - } - - /** - * Is this a state in which the handshake has completed? - * @return true if the handshake is complete - */ - boolean isHandshakeComplete() { - return this.state.isHandshakeComplete(); - } - - /** - * Forwards to RoleChanger. See there. - * @param role - */ - void sendRoleRequestIfNotPending(Role role) { - try { - roleChanger.sendRoleRequestIfNotPending(role); - } catch (IOException e) { - log.error("Disconnecting switch {} due to IO Error: {}", - getSwitchInfoString(), e.getMessage()); - channel.close(); - } - } - - /** - * Forwards to RoleChanger. See there. - * @param role - */ - void sendRoleRequest(Role role) { - try { - roleChanger.sendRoleRequest(role); - } catch (IOException e) { - log.error("Disconnecting switch {} due to IO Error: {}", - getSwitchInfoString(), e.getMessage()); - channel.close(); - } - } - - - @Override - @LogMessageDoc(message="New switch connection from {ip address}", - explanation="A new switch has connected from the " + - "specified IP address") - public void channelConnected(ChannelHandlerContext ctx, - ChannelStateEvent e) throws Exception { - counters.switchConnected.updateCounterWithFlush(); - channel = e.getChannel(); - log.info("New switch connection from {}", - channel.getRemoteAddress()); - sendHandShakeMessage(OFType.HELLO); - setState(ChannelState.WAIT_HELLO); - } - - @Override - @LogMessageDoc(message="Disconnected switch {switch information}", - explanation="The specified switch has disconnected.") - public void channelDisconnected(ChannelHandlerContext ctx, - ChannelStateEvent e) throws Exception { - controller.removeSwitchChannel(this); - if (this.sw != null) { - // TODO: switchDisconnected() will check if we've previously - // activated the switch. Nevertheless, we might want to check - // here as well. - controller.switchDisconnected(this.sw); - this.sw.setConnected(false); - } - - log.info("Disconnected switch {}", getSwitchInfoString()); - } - - @Override - @LogMessageDocs({ - @LogMessageDoc(level="ERROR", - message="Disconnecting switch {switch} due to read timeout", - explanation="The connected switch has failed to send any " + - "messages or respond to echo requests", - recommendation=LogMessageDoc.CHECK_SWITCH), - @LogMessageDoc(level="ERROR", - message="Disconnecting switch {switch}: failed to " + - "complete handshake", - explanation="The switch did not respond correctly " + - "to handshake messages", - recommendation=LogMessageDoc.CHECK_SWITCH), - @LogMessageDoc(level="ERROR", - message="Disconnecting switch {switch} due to IO Error: {}", - explanation="There was an error communicating with the switch", - recommendation=LogMessageDoc.CHECK_SWITCH), - @LogMessageDoc(level="ERROR", - message="Disconnecting switch {switch} due to switch " + - "state error: {error}", - explanation="The switch sent an unexpected message", - recommendation=LogMessageDoc.CHECK_SWITCH), - @LogMessageDoc(level="ERROR", - message="Disconnecting switch {switch} due to " + - "message parse failure", - explanation="Could not parse a message from the switch", - recommendation=LogMessageDoc.CHECK_SWITCH), - @LogMessageDoc(level="ERROR", - message="Terminating controller due to storage exception", - explanation=Controller.ERROR_DATABASE, - recommendation=LogMessageDoc.CHECK_CONTROLLER), - @LogMessageDoc(level="ERROR", - message="Could not process message: queue full", - explanation="OpenFlow messages are arriving faster than " + - " the controller can process them.", - recommendation=LogMessageDoc.CHECK_CONTROLLER), - @LogMessageDoc(level="ERROR", - message="Error while processing message " + - "from switch {switch} {cause}", - explanation="An error occurred processing the switch message", - recommendation=LogMessageDoc.GENERIC_ACTION) - }) - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) - throws Exception { - if (e.getCause() instanceof ReadTimeoutException) { - // switch timeout - log.error("Disconnecting switch {} due to read timeout", - getSwitchInfoString()); - counters.switchDisconnectReadTimeout.updateCounterWithFlush(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof HandshakeTimeoutException) { - log.error("Disconnecting switch {}: failed to complete handshake", - getSwitchInfoString()); - counters.switchDisconnectHandshakeTimeout.updateCounterWithFlush(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof ClosedChannelException) { - log.debug("Channel for sw {} already closed", getSwitchInfoString()); - } else if (e.getCause() instanceof IOException) { - log.error("Disconnecting switch {} due to IO Error: {}", - getSwitchInfoString(), e.getCause().getMessage()); - if (log.isDebugEnabled()) { - // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); - } - counters.switchDisconnectIOError.updateCounterWithFlush(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof SwitchStateException) { - log.error("Disconnecting switch {} due to switch state error: {}", - getSwitchInfoString(), e.getCause().getMessage()); - if (log.isDebugEnabled()) { - // still print stack trace if debug is enabled - log.debug("StackTrace for previous Exception: ", e.getCause()); - } - counters.switchDisconnectSwitchStateException.updateCounterWithFlush(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof MessageParseException) { - log.error("Disconnecting switch " - + getSwitchInfoString() + - " due to message parse failure", - e.getCause()); - counters.switchDisconnectParseError.updateCounterWithFlush(); - ctx.getChannel().close(); - } else if (e.getCause() instanceof StorageException) { - log.error("Terminating controller due to storage exception", - e.getCause()); - this.controller.terminate(); - } else if (e.getCause() instanceof RejectedExecutionException) { - log.warn("Could not process message: queue full"); - counters.rejectedExecutionException.updateCounterWithFlush(); - } else { - log.error("Error while processing message from switch " - + getSwitchInfoString() - + "state " + this.state, e.getCause()); - counters.switchDisconnectOtherException.updateCounterWithFlush(); - ctx.getChannel().close(); - } - } - - @Override - public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) - throws Exception { - OFMessage m = BasicFactory.getInstance().getMessage(OFType.ECHO_REQUEST); - e.getChannel().write(Collections.singletonList(m)); - } - - @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) - throws Exception { - if (e.getMessage() instanceof List) { - @SuppressWarnings("unchecked") - List<OFMessage> msglist = (List<OFMessage>)e.getMessage(); - - LoadMonitor.LoadLevel loadlevel; - int packets_dropped = 0; - int packets_allowed = 0; - int lldps_allowed = 0; - - if (this.controller.overload_drop) { - loadlevel = this.controller.loadmonitor.getLoadLevel(); - } - else { - loadlevel = LoadMonitor.LoadLevel.OK; - } - - for (OFMessage ofm : msglist) { - counters.messageReceived.updateCounterNoFlush(); - // Per-switch input throttling - if (sw != null && sw.inputThrottled(ofm)) { - counters.messageInputThrottled.updateCounterNoFlush(); - continue; - } - try { - if (this.controller.overload_drop && - !loadlevel.equals(LoadMonitor.LoadLevel.OK)) { - switch (ofm.getType()) { - case PACKET_IN: - switch (loadlevel) { - case VERYHIGH: - // Drop all packet-ins, including LLDP/BDDPs - packets_dropped++; - continue; - case HIGH: - // Drop all packet-ins, except LLDP/BDDPs - byte[] data = ((OFPacketIn)ofm).getPacketData(); - if (data.length > 14) { - if (((data[12] == (byte)0x88) && - (data[13] == (byte)0xcc)) || - ((data[12] == (byte)0x89) && - (data[13] == (byte)0x42))) { - lldps_allowed++; - packets_allowed++; - break; - } - } - packets_dropped++; - continue; - default: - // Load not high, go ahead and process msg - packets_allowed++; - break; - } - break; - default: - // Process all non-packet-ins - packets_allowed++; - break; - } - } - - // Do the actual packet processing - state.processOFMessage(this, ofm); - - } - catch (Exception ex) { - // We are the last handler in the stream, so run the - // exception through the channel again by passing in - // ctx.getChannel(). - Channels.fireExceptionCaught(ctx.getChannel(), ex); - } - } - - if (loadlevel != LoadMonitor.LoadLevel.OK) { - if (log.isDebugEnabled()) { - log.debug( - "Overload: Detected {}, packets dropped={}", - loadlevel.toString(), packets_dropped); - log.debug( - "Overload: Packets allowed={} (LLDP/BDDPs allowed={})", - packets_allowed, lldps_allowed); - } - } - // Flush all thread local queues etc. generated by this train - // of messages. - this.controller.flushAll(); - } - else { - Channels.fireExceptionCaught(ctx.getChannel(), - new AssertionError("Message received from Channel is not a list")); - } - } - - - /** - * Get a useable error string from the OFError. - * @param error - * @return - */ - public static String getErrorString(OFError error) { - // TODO: this really should be OFError.toString. Sigh. - int etint = 0xffff & error.getErrorType(); - if (etint < 0 || etint >= OFErrorType.values().length) { - return String.format("Unknown error type %d", etint); - } - OFErrorType et = OFErrorType.values()[etint]; - switch (et) { - case OFPET_HELLO_FAILED: - OFHelloFailedCode hfc = - OFHelloFailedCode.values()[0xffff & error.getErrorCode()]; - return String.format("Error %s %s", et, hfc); - case OFPET_BAD_REQUEST: - OFBadRequestCode brc = - OFBadRequestCode.values()[0xffff & error.getErrorCode()]; - return String.format("Error %s %s", et, brc); - case OFPET_BAD_ACTION: - OFBadActionCode bac = - OFBadActionCode.values()[0xffff & error.getErrorCode()]; - return String.format("Error %s %s", et, bac); - case OFPET_FLOW_MOD_FAILED: - OFFlowModFailedCode fmfc = - OFFlowModFailedCode.values()[0xffff & error.getErrorCode()]; - return String.format("Error %s %s", et, fmfc); - case OFPET_PORT_MOD_FAILED: - OFPortModFailedCode pmfc = - OFPortModFailedCode.values()[0xffff & error.getErrorCode()]; - return String.format("Error %s %s", et, pmfc); - case OFPET_QUEUE_OP_FAILED: - OFQueueOpFailedCode qofc = - OFQueueOpFailedCode.values()[0xffff & error.getErrorCode()]; - return String.format("Error %s %s", et, qofc); - case OFPET_VENDOR_ERROR: - // no codes known for vendor error - return String.format("Error %s", et); - } - return null; - } - - private void dispatchMessage(OFMessage m) throws IOException { - // handleMessage will count - this.controller.handleMessage(this.sw, m, null); - } - - /** - * Return a string describing this switch based on the already available - * information (DPID and/or remote socket) - * @return - */ - private String getSwitchInfoString() { - if (sw != null) - return sw.toString(); - String channelString; - if (channel == null || channel.getRemoteAddress() == null) { - channelString = "?"; - } else { - channelString = channel.getRemoteAddress().toString(); - } - String dpidString; - if (featuresReply == null) { - dpidString = "?"; - } else { - dpidString = HexString.toHexString(featuresReply.getDatapathId()); - } - return String.format("[%s DPID[%s]]", channelString, dpidString); - } - - /** - * Update the channels state. Only called from the state machine. - * TODO: enforce restricted state transitions - * @param state - */ - private void setState(ChannelState state) { - this.state = state; - } - - /** - * Send a message to the switch using the handshake transactions ids. - * @throws IOException - */ - private void sendHandShakeMessage(OFType type) throws IOException { - // Send initial Features Request - OFMessage m = BasicFactory.getInstance().getMessage(type); - m.setXid(handshakeTransactionIds--); - channel.write(Collections.singletonList(m)); - } - - /** - * Send an setL2TableSet message to the switch. - */ - private void sendHandshakeL2TableSet() { - OFVendor l2TableSet = (OFVendor) - BasicFactory.getInstance().getMessage(OFType.VENDOR); - l2TableSet.setXid(handshakeTransactionIds--); - OFBsnL2TableSetVendorData l2TableSetData = - new OFBsnL2TableSetVendorData(true, - controller.getCoreFlowPriority()); - l2TableSet.setVendor(OFBigSwitchVendorData.BSN_VENDOR_ID); - l2TableSet.setVendorData(l2TableSetData); - l2TableSet.setLengthU(OFVendor.MINIMUM_LENGTH + - l2TableSetData.getLength()); - channel.write(Collections.singletonList(l2TableSet)); - } - - - private void gotoWaitInitialRoleState() { - // We need to set the new state /before/ we call addSwitchChannel - // because addSwitchChannel will eventually call setRole - // which can in turn decide that the switch doesn't support - // roles and transition the state straight to MASTER. - setState(ChannelState.WAIT_INITIAL_ROLE); - controller.addSwitchChannelAndSendInitialRole(this); - } - - /** - * Send the configuration requests to tell the switch we want full - * packets - * @throws IOException - */ - private void sendHandshakeSetConfig() throws IOException { - List<OFMessage> msglist = new ArrayList<OFMessage>(3); - - // Ensure we receive the full packet via PacketIn - // FIXME: We don't set the reassembly flags. - OFSetConfig configSet = (OFSetConfig) BasicFactory.getInstance() - .getMessage(OFType.SET_CONFIG); - configSet.setMissSendLength((short) 0xffff) - .setLengthU(OFSwitchConfig.MINIMUM_LENGTH); - configSet.setXid(handshakeTransactionIds--); - msglist.add(configSet); - - // Barrier - OFBarrierRequest barrier = (OFBarrierRequest) BasicFactory.getInstance() - .getMessage(OFType.BARRIER_REQUEST); - barrier.setXid(handshakeTransactionIds--); - msglist.add(barrier); - - // Verify (need barrier?) - OFGetConfigRequest configReq = (OFGetConfigRequest) - BasicFactory.getInstance().getMessage(OFType.GET_CONFIG_REQUEST); - configReq.setXid(handshakeTransactionIds--); - msglist.add(configReq); - channel.write(msglist); - } - - /** - * send a description state request - * @throws IOException - */ - private void sendHandshakeDescriptionStatsRequest() throws IOException { - // Get Description to set switch-specific flags - OFStatisticsRequest req = new OFStatisticsRequest(); - req.setStatisticType(OFStatisticsType.DESC); - req.setXid(handshakeTransactionIds--); - - channel.write(Collections.singletonList(req)); - } - - - /** - * Read switch properties from storage and set switch attributes accordingly - */ - private void readPropertyFromStorage() { - // At this time, also set other switch properties from storage - boolean is_core_switch = false; - IResultSet resultSet = null; - try { - String swid = sw.getStringId(); - resultSet = this.controller.getStorageSourceService() - .getRow(Controller.SWITCH_CONFIG_TABLE_NAME, swid); - for (Iterator<IResultSet> it = - resultSet.iterator(); it.hasNext();) { - is_core_switch = it.next() - .getBoolean(Controller.SWITCH_CONFIG_CORE_SWITCH); - if (log.isDebugEnabled()) { - log.debug("Reading SWITCH_IS_CORE_SWITCH " + - "config for switch={}, is-core={}", - sw, is_core_switch); - } - } - } - finally { - if (resultSet != null) - resultSet.close(); - } - if (is_core_switch) { - sw.setAttribute(IOFSwitch.SWITCH_IS_CORE_SWITCH, - Boolean.valueOf(true)); - } - } - - ChannelState getStateForTesting() { - return state; - } - - void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) { - roleChanger = new RoleChanger(roleTimeoutMs); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java deleted file mode 100644 index eca67bd97ca289fa5246edbb4196d9f0216e98c5..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright 2012, Big Switch Networks, Inc. - * - * 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.core.internal; - -import java.util.concurrent.TimeUnit; - -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.threadpool.IThreadPoolService; - -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; - -/** - * A concrete implementation that handles asynchronously receiving - * OFFeaturesReply - * - * @author Shudong Zhou - */ -public class OFFeaturesReplyFuture extends - OFMessageFuture<OFFeaturesReply> { - - protected volatile boolean finished; - - public OFFeaturesReplyFuture(IThreadPoolService tp, - IOFSwitch sw, int transactionId) { - super(tp, sw, OFType.FEATURES_REPLY, transactionId); - init(); - } - - public OFFeaturesReplyFuture(IThreadPoolService tp, - IOFSwitch sw, int transactionId, long timeout, TimeUnit unit) { - super(tp, sw, OFType.FEATURES_REPLY, transactionId, timeout, unit); - init(); - } - - private void init() { - this.finished = false; - this.result = null; - } - - @Override - protected void handleReply(IOFSwitch sw, OFMessage msg) { - this.result = (OFFeaturesReply) msg; - this.finished = true; - } - - @Override - protected boolean isFinished() { - return finished; - } - - @Override - protected void unRegister() { - super.unRegister(); - sw.cancelFeaturesReply(transactionId); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java deleted file mode 100644 index 25edf396c943dfce728f79610910162ebd608a12..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java +++ /dev/null @@ -1,60 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.frame.FrameDecoder; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.OFMessageFactory; - -/** - * Decode an openflow message from a Channel, for use in a netty - * pipeline - * @author readams - */ -public class OFMessageDecoder extends FrameDecoder { - - OFMessageFactory factory = BasicFactory.getInstance(); - - @Override - protected Object decode(ChannelHandlerContext ctx, Channel channel, - ChannelBuffer buffer) throws Exception { - if (!channel.isConnected()) { - // In testing, I see decode being called AFTER decode last. - // This check avoids that from reading curroupted frames - return null; - } - - List<OFMessage> message = factory.parseMessage(buffer); - return message; - } - - @Override - protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, - ChannelBuffer buffer) throws Exception { - // This is not strictly needed atthis time. It is used to detect - // connection reset detection from netty (for debug) - return null; - } - -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java deleted file mode 100644 index 6be5f9a1d524b51e85af216f70d9a4800aed0ad6..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java +++ /dev/null @@ -1,56 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; -import org.openflow.protocol.OFMessage; - -/** - * Encode an openflow message for output into a ChannelBuffer, for use in a - * netty pipeline - * @author readams - */ -public class OFMessageEncoder extends OneToOneEncoder { - - @Override - protected Object encode(ChannelHandlerContext ctx, Channel channel, - Object msg) throws Exception { - if (!( msg instanceof List)) - return msg; - - @SuppressWarnings("unchecked") - List<OFMessage> msglist = (List<OFMessage>)msg; - int size = 0; - for (OFMessage ofm : msglist) { - size += ofm.getLengthU(); - } - - ChannelBuffer buf = ChannelBuffers.buffer(size);; - for (OFMessage ofm : msglist) { - ofm.writeTo(buf); - } - return buf; - } - -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java deleted file mode 100644 index 1fc9c135330d6189652fca4b37aac903bce5bf0d..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java +++ /dev/null @@ -1,171 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; - -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.threadpool.IThreadPoolService; - -/** - * A Future object used to retrieve asynchronous OFMessage replies. Unregisters - * and cancels itself by default after 60 seconds. This class is meant to be - * sub-classed and proper behavior added to the handleReply method, and - * termination of the Future to be handled in the isFinished method. - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public abstract class OFMessageFuture<V> implements Future<V> { - - protected IThreadPoolService threadPool; - protected volatile boolean canceled; - protected CountDownLatch latch; - protected OFType responseType; - protected volatile V result; - protected IOFSwitch sw; - protected Runnable timeoutTimer; - protected int transactionId; - protected static final long DEFAULT_TIMEOUT = 60; - protected static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.SECONDS; - - public OFMessageFuture(IThreadPoolService tp, - IOFSwitch sw, OFType responseType, int transactionId) { - this(tp, sw, responseType, transactionId, - DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT); - } - - public OFMessageFuture(IThreadPoolService tp, - IOFSwitch sw, OFType responseType, int transactionId, long timeout, TimeUnit unit) { - this.threadPool = tp; - this.canceled = false; - this.latch = new CountDownLatch(1); - this.responseType = responseType; - this.sw = sw; - this.transactionId = transactionId; - - final OFMessageFuture<V> future = this; - timeoutTimer = new Runnable() { - @Override - public void run() { - if (timeoutTimer == this) - future.cancel(true); - } - }; - threadPool.getScheduledExecutor().schedule(timeoutTimer, timeout, unit); - } - - protected void unRegister() { - this.timeoutTimer = null; - } - - - // TODO: msg should be generic! - public void deliverFuture(IOFSwitch sw, OFMessage msg) { - if (transactionId == msg.getXid()) { - handleReply(sw, msg); - if (isFinished()) { - unRegister(); - this.latch.countDown(); - } - } - } - - /** - * Used to handle the specific expected message this Future was reigstered - * for, the specified msg parameter is guaranteed to match the type and - * transaction id specified. - * @param sw - * @param msg - * @return - */ - protected abstract void handleReply(IOFSwitch sw, OFMessage msg); - - /** - * Called directly after handleReply, subclasses implement this method to - * indicate when the future can deregister itself from receiving future - * messages, and when it is safe to return the results to any waiting - * threads. - * @return when this Future has completed its work - */ - protected abstract boolean isFinished(); - - /* (non-Javadoc) - * @see java.util.concurrent.Future#cancel(boolean) - */ - @Override - public boolean cancel(boolean mayInterruptIfRunning) { - if (isDone()) { - return false; - } else { - unRegister(); - canceled = true; - this.latch.countDown(); - return !isDone(); - } - } - - /* (non-Javadoc) - * @see java.util.concurrent.Future#isCancelled() - */ - @Override - public boolean isCancelled() { - return canceled; - } - - /* (non-Javadoc) - * @see java.util.concurrent.Future#isDone() - */ - @Override - public boolean isDone() { - return this.latch.getCount() == 0; - } - - /* (non-Javadoc) - * @see java.util.concurrent.Future#get() - */ - @Override - public V get() throws InterruptedException, ExecutionException { - this.latch.await(); - return result; - } - - /* (non-Javadoc) - * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit) - */ - @Override - public V get(long timeout, TimeUnit unit) throws InterruptedException, - ExecutionException, TimeoutException { - this.latch.await(timeout, unit); - return result; - } - - public int getTransactionId() { - return transactionId; - } - - public void setTransactionId(int transactionId) { - this.transactionId = transactionId; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java deleted file mode 100644 index 4d3f733a6ed1d3e6b7dbba272643680877f9e982..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java +++ /dev/null @@ -1,80 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; - -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.threadpool.IThreadPoolService; - -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFStatisticsReply; -import org.openflow.protocol.OFType; -import org.openflow.protocol.statistics.OFStatistics; - -/** - * A concrete implementation that handles asynchronously receiving OFStatistics - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFStatisticsFuture extends - OFMessageFuture<List<OFStatistics>> { - - protected volatile boolean finished; - - public OFStatisticsFuture(IThreadPoolService tp, - IOFSwitch sw, int transactionId) { - super(tp, sw, OFType.STATS_REPLY, transactionId); - init(); - } - - public OFStatisticsFuture(IThreadPoolService tp, - IOFSwitch sw, int transactionId, long timeout, TimeUnit unit) { - super(tp, sw, OFType.STATS_REPLY, transactionId, timeout, unit); - init(); - } - - private void init() { - this.finished = false; - this.result = new CopyOnWriteArrayList<OFStatistics>(); - } - - @Override - protected void handleReply(IOFSwitch sw, OFMessage msg) { - OFStatisticsReply sr = (OFStatisticsReply) msg; - synchronized (this.result) { - this.result.addAll(sr.getStatistics()); - if ((sr.getFlags() & 0x1) == 0) { - this.finished = true; - } - } - } - - @Override - protected boolean isFinished() { - return finished; - } - - @Override - protected void unRegister() { - super.unRegister(); - sw.cancelStatisticsReply(transactionId); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java new file mode 100644 index 0000000000000000000000000000000000000000..ddfd008720a6853262905afeb7072cf91c99c3f5 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java @@ -0,0 +1,116 @@ +package net.floodlightcontroller.core.internal; + +import java.util.concurrent.TimeUnit; + +import org.jboss.netty.util.Timeout; +import org.jboss.netty.util.Timer; +import org.jboss.netty.util.TimerTask; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; + +/** + * This class is a plugin that can be used by applications to tap into the + * switch handshake. It operates much like the switch handshake. Messages should + * be sent upon entering the plugin and OF response messages should be handled + * just like any part of the switch handshake. + * + * @author Jason Parraga <jason.parraga@bigswitch.com> + */ +public abstract class OFSwitchAppHandshakePlugin { + + private static final Logger log = LoggerFactory.getLogger(OFSwitchAppHandshakePlugin.class); + + private WaitAppHandshakeState state; + @edu.umd.cs.findbugs.annotations.SuppressWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") + private IOFSwitch sw; + private volatile Timeout timeout; + + private final PluginResult defaultResult; + private final int timeoutS; + + /** + * Constructor for OFSwitchAppHandshakePlugin + * @param defaultResult the default result in the event of a timeout + * @param defaultTimeoutS the timeout length in seconds + */ + protected OFSwitchAppHandshakePlugin(PluginResult defaultResult, int timeoutS){ + Preconditions.checkNotNull(defaultResult, "defaultResult"); + Preconditions.checkNotNull(timeoutS, "timeoutS"); + + this.defaultResult = defaultResult; + this.timeoutS = timeoutS; + } + + /** + * Process incoming OF Messages + * + * @param m The OF Message received + */ + protected abstract void processOFMessage(OFMessage m); + + /** + * Enter this plugin. Should be used to send messages. + */ + protected abstract void enterPlugin(); + + /** + * Gets the switch associated with the handshake for use by the plugin + * writer. + * + * @return the switch associated with the handshake. + */ + protected IOFSwitch getSwitch() { + return this.sw; + } + + /** + * Initialization for plugin called by the OFSwitchHandshakeHandler + * + * @param state the current state of the OFSwitchHandshakeHandler + * @param sw the current switch of the OFSwitchHandshakeHandler + */ + final void init(WaitAppHandshakeState state, IOFSwitch sw, Timer timer) { + this.state = state; + this.sw = sw; + this.timeout = timer.newTimeout(new PluginTimeoutTask(), timeoutS, TimeUnit.SECONDS); + } + + /** + * Called to denote that the plugin has finished + * + * @param result + * the result of the plugin in regards to handshaking + */ + protected final void exitPlugin(PluginResult result) { + timeout.cancel(); + state.exitPlugin(result); + } + + /** + * Plugin timeout task that will exit the plugin + * with the default result value when timed out. + * + */ + private final class PluginTimeoutTask implements TimerTask { + + @Override + public void run(Timeout timeout) throws Exception { + if (!timeout.isCancelled()) { + log.warn("App handshake plugin for {} timed out. Returning result {}.", + sw, defaultResult); + exitPlugin(defaultResult); + } + } + } + + public enum PluginResultType { + CONTINUE(), + DISCONNECT(), + QUARANTINE(); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..90c7d4654a6d6d8b1fd670d65d456b68053fde3d --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java @@ -0,0 +1,1886 @@ +package net.floodlightcontroller.core.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nonnull; + +import org.jboss.netty.util.Timer; +import net.floodlightcontroller.core.GenTableMap; +import net.floodlightcontroller.core.HARole; +import net.floodlightcontroller.core.IOFConnection; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.IOFSwitch.SwitchStatus; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.PortChangeEvent; +import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.core.annotations.LogMessageDoc; +import net.floodlightcontroller.core.annotations.LogMessageDocs; +import net.floodlightcontroller.core.internal.OFSwitchAppHandshakePlugin.PluginResultType; +import org.projectfloodlight.openflow.protocol.OFBadRequestCode; +import org.projectfloodlight.openflow.protocol.OFBarrierReply; +import org.projectfloodlight.openflow.protocol.OFBarrierRequest; +import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply; +import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsRequest; +import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsReply; +import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsRequest; +import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsReply; +import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsRequest; +import org.projectfloodlight.openflow.protocol.OFBsnSetL2TableRequest; +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.projectfloodlight.openflow.protocol.OFDescStatsReply; +import org.projectfloodlight.openflow.protocol.OFDescStatsRequest; +import org.projectfloodlight.openflow.protocol.OFErrorMsg; +import org.projectfloodlight.openflow.protocol.OFErrorType; +import org.projectfloodlight.openflow.protocol.OFExperimenter; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode; +import org.projectfloodlight.openflow.protocol.OFFlowRemoved; +import org.projectfloodlight.openflow.protocol.OFGetConfigReply; +import org.projectfloodlight.openflow.protocol.OFGetConfigRequest; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole; +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply; +import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; +import org.projectfloodlight.openflow.protocol.OFPortStatus; +import org.projectfloodlight.openflow.protocol.OFQueueGetConfigReply; +import org.projectfloodlight.openflow.protocol.OFRoleReply; +import org.projectfloodlight.openflow.protocol.OFRoleRequest; +import org.projectfloodlight.openflow.protocol.OFSetConfig; +import org.projectfloodlight.openflow.protocol.OFStatsReply; +import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; +import org.projectfloodlight.openflow.protocol.OFStatsRequestFlags; +import org.projectfloodlight.openflow.protocol.OFStatsType; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg; +import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFAuxId; +import org.projectfloodlight.openflow.types.U64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +/** + * Switch handler deals with the switch connection and dispatches + * switch messages to the appropriate locations. These messages + * are typically received by the channel handler first and piped here. + * + * @author Jason Parraga <jason.parraga@bigswitch.com> + */ +public class OFSwitchHandshakeHandler implements IOFConnectionListener { + private static final Logger log = LoggerFactory.getLogger(OFSwitchHandshakeHandler.class); + + private final IOFSwitchManager switchManager; + private final RoleManager roleManager; + private final IOFConnectionBackend mainConnection; + private final SwitchManagerCounters switchManagerCounters; + private IOFSwitchBackend sw; + private final Map<OFAuxId, IOFConnectionBackend> auxConnections; + private volatile OFSwitchHandshakeState state; + private RoleChanger roleChanger; + // Default to 1.3 - This is overwritten by the features reply + private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); + private final OFFeaturesReply featuresReply; + private final Timer timer; + + private final ArrayList<OFPortStatus> pendingPortStatusMsg; + + /** transaction Ids to use during handshake. Since only one thread + * calls into the OFChannelHandler we don't need atomic. + * We will count down + */ + private long handshakeTransactionIds = 0x00FFFFFFFFL; + + /* Exponential backoff of master role assertion */ + private final long MAX_ASSERT_TIME_INTERVAL_NS = TimeUnit.SECONDS.toNanos(120); + private final long DEFAULT_ROLE_TIMEOUT_NS = TimeUnit.SECONDS.toNanos(10); + + protected OFPortDescStatsReply portDescStats; + + /** + * When we remove a pending role request and set the role on the switch + * we use this enum to indicate how we arrived at the decision. + * @author gregor + */ + private enum RoleRecvStatus { + /** We received a role reply message from the switch */ + RECEIVED_REPLY, + /** The switch returned an error indicated that roles are not + * supported*/ + UNSUPPORTED, + /** The request timed out */ + NO_REPLY; + } + /** + * A utility class to handle role requests and replies for this channel. + * After a role request is submitted the role changer keeps track of the + * pending request, collects the reply (if any) and times out the request + * if necessary. + * + * To simplify role handling we only keep track of the /last/ pending + * role reply send to the switch. If multiple requests are pending and + * we receive replies for earlier requests we ignore them. However, this + * way of handling pending requests implies that we could wait forever if + * a new request is submitted before the timeout triggers. If necessary + * we could work around that though. + * @author gregor + */ + private class RoleChanger { + // indicates that a request is currently pending + // needs to be volatile to allow correct double-check idiom + private volatile boolean requestPending; + // the transaction Id of the pending request + private long pendingXid; + // the role that's pending + private OFControllerRole pendingRole; + // system time in NS when we send the request + private long roleSubmitTimeNs; + // the timeout to use + private final long roleTimeoutNs; + private long lastAssertTimeNs; + private long assertTimeIntervalNs = TimeUnit.SECONDS.toNanos(1); + + public RoleChanger(long roleTimeoutNs) { + this.roleTimeoutNs = roleTimeoutNs; + // System.nanoTime() may be negative -- prime the roleSubmitTime as + // "long ago in the past" to be robust against it. + this.roleSubmitTimeNs = System.nanoTime() - (2 * roleTimeoutNs); + this.lastAssertTimeNs = System.nanoTime() - (2 * assertTimeIntervalNs); + this.requestPending = false; + this.pendingXid = -1; + this.pendingRole = null; + } + + /** + * Send Nicira role request message to the switch requesting the + * specified role. + * + * @param role role to request + */ + private long sendNiciraRoleRequest(OFControllerRole role){ + + long xid; + // Construct the role request message + if(factory.getVersion().compareTo(OFVersion.OF_12) < 0) { + OFNiciraControllerRoleRequest.Builder builder = + factory.buildNiciraControllerRoleRequest(); + xid = factory.nextXid(); + builder.setXid(xid); + + OFNiciraControllerRole niciraRole = NiciraRoleUtils.ofRoleToNiciraRole(role); + builder.setRole(niciraRole); + OFNiciraControllerRoleRequest roleRequest = builder.build(); + // Send it to the switch + mainConnection.write(roleRequest); + } else { + // send an OF 1.2+ role request + OFRoleRequest roleRequest = factory.buildRoleRequest() + // we don't use the generation id scheme for now, + // switch initializes to 0, we keep it at 0 + .setGenerationId(U64.of(0)) + .setRole(role) + .build(); + xid = roleRequest.getXid(); + mainConnection.write(roleRequest); + } + return xid; + } + + /** + * Send a role request for the given role only if no other role + * request is currently pending. + * @param role The role to send to the switch. + * @throws IOException + */ + @LogMessageDoc(level="WARN", + message="Reasserting master role on switch {SWITCH}, " + + "likely a configruation error with multiple masters", + explanation="The controller keeps getting permission error " + + "from switch, likely due to switch connected to another " + + "controller also in master mode", + recommendation=LogMessageDoc.CHECK_SWITCH) + synchronized void sendRoleRequestIfNotPending(OFControllerRole role) + throws IOException { + long now = System.nanoTime(); + if (now - lastAssertTimeNs < assertTimeIntervalNs) { + return; + } + + lastAssertTimeNs = now; + if (assertTimeIntervalNs < MAX_ASSERT_TIME_INTERVAL_NS) { // 2 minutes max + assertTimeIntervalNs <<= 1; + } else if (role == OFControllerRole.ROLE_MASTER){ + log.warn("Reasserting master role on switch {}, " + + "likely a switch config error with multiple masters", + role, sw); + } + if (!requestPending) + sendRoleRequest(role); + else + switchManagerCounters.roleNotResentBecauseRolePending.increment(); + } + + /** + * Send a role request with the given role to the switch. + * + * Send a role request with the given role to the switch and update + * the pending request and timestamp. + * + * @param role + * @throws IOException + */ + synchronized void sendRoleRequest(OFControllerRole role) throws IOException { + /* + * There are three cases to consider for SUPPORTS_NX_ROLE: + * + * 1) unset. We have neither received a role reply from the + * switch nor has a request timed out. Send a request. + * 2) TRUE: We've already send a request earlier and received + * a reply. The switch supports role and we should send one. + * 3) FALSE: We have already send a role and received an error. + * The switch does not support roles. Don't send a role request, + * set the switch's role directly. + */ + Boolean supportsNxRole = (Boolean) + sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE); + if ((supportsNxRole != null) && !supportsNxRole) { + setSwitchRole(role, RoleRecvStatus.UNSUPPORTED); + } else { + pendingXid = sendNiciraRoleRequest(role); + pendingRole = role; + this.roleSubmitTimeNs = System.nanoTime(); + requestPending = true; + } + } + + /** + * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE. + * + * Check if a request is pending and if the received reply matches the + * the expected pending reply (we check both role and xid) we set + * the role for the switch/channel. + * + * If a request is pending but doesn't match the reply we ignore it. + * + * If no request is pending we disconnect. + * + * @param xid + * @param role + * @throws SwitchStateException if no request is pending + */ + synchronized void deliverRoleReply(long xid, OFControllerRole role) { + if (!requestPending) { + // Maybe don't disconnect if the role reply we received is + // for the same role we are already in. + String msg = String.format("Switch: [%s], State: [%s], " + + "received unexpected RoleReply[%s]. " + + "No roles are pending", + OFSwitchHandshakeHandler.this.getSwitchInfoString(), + OFSwitchHandshakeHandler.this.state.toString(), + role); + throw new SwitchStateException(msg); + } + + if (pendingXid == xid && pendingRole == role) { + log.debug("[{}] Received role reply message setting role to {}", + getDpid(), role); + switchManagerCounters.roleReplyReceived.increment(); + setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); + } else { + log.debug("[{}] Received stale or unexpected role reply " + + "{}, xid={}. Ignoring. " + + "Waiting for {}, xid={}", + new Object[] { getDpid(), role, xid, + pendingRole, pendingXid }); + } + } + + /** + * Called if we receive an error message. If the xid matches the + * pending request we handle it otherwise we ignore it. We also + * set SWITCH_SUPPORTS_NX_ROLE to false. + * + * Note: since we only keep the last pending request we might get + * error messages for earlier role requests that we won't be able + * to handle + * @param xid + * @return true if the error was handled by us, false otherwise + * @throws SwitchStateException if the error was for the pending + * role request but was unexpected + */ + synchronized boolean deliverError(OFErrorMsg error) { + if (!requestPending) + return false; + + if (pendingXid == error.getXid()) { + if (error.getErrType() == OFErrorType.BAD_REQUEST) { + switchManagerCounters.roleReplyErrorUnsupported.increment(); + setSwitchRole(pendingRole, RoleRecvStatus.UNSUPPORTED); + } else { + // TODO: Is this the right thing to do if we receive + // some other error besides a bad request error? + // Presumably that means the switch did actually + // understand the role request message, but there + // was some other error from processing the message. + // OF 1.2 specifies a ROLE_REQUEST_FAILED + // error code, but it doesn't look like the Nicira + // role request has that. Should check OVS source + // code to see if it's possible for any other errors + // to be returned. + // If we received an error the switch is not + // in the correct role, so we need to disconnect it. + // We could also resend the request but then we need to + // check if there are other pending request in which + // case we shouldn't resend. If we do resend we need + // to make sure that the switch eventually accepts one + // of our requests or disconnect the switch. This feels + // cumbersome. + String msg = String.format("Switch: [%s], State: [%s], " + + "Unexpected error %s in respone to our " + + "role request for %s.", + OFSwitchHandshakeHandler.this.getSwitchInfoString(), + OFSwitchHandshakeHandler.this.state.toString(), + error.toString(), + pendingRole); + throw new SwitchStateException(msg); + } + return true; + } + return false; + } + + /** + * Check if a pending role request has timed out. + */ + void checkTimeout() { + if (!requestPending) + return; + synchronized(this) { + if (!requestPending) + return; + long now = System.nanoTime(); + if (now - this.roleSubmitTimeNs > roleTimeoutNs) { + // timeout triggered. + switchManagerCounters.roleReplyTimeout.increment(); + setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY); + } + } + } + + /** + * Set the role for this switch / channel. + * + * If the status indicates that we received a reply we set the role. + * If the status indicates otherwise we disconnect the switch if + * the role is SLAVE. + * + * "Setting a role" means setting the appropriate ChannelState, + * setting the flags on the switch and + * notifying Controller.java about new role of the switch + * + * @param role The role to set. + * @param status How we derived at the decision to set this status. + */ + synchronized private void setSwitchRole(OFControllerRole role, RoleRecvStatus status) { + requestPending = false; + if (status == RoleRecvStatus.RECEIVED_REPLY) + sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); + else + sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); + sw.setControllerRole(role); + + if (role != OFControllerRole.ROLE_SLAVE) { + OFSwitchHandshakeHandler.this.setState(new MasterState()); + } else { + if (status != RoleRecvStatus.RECEIVED_REPLY) { + if (log.isDebugEnabled()) { + log.debug("Disconnecting switch {}. Doesn't support role" + + "({}) request and controller is now SLAVE", + getSwitchInfoString(), status); + } + // the disconnect will trigger a switch removed to + // controller so no need to signal anything else + sw.disconnect(); + } else { + OFSwitchHandshakeHandler.this.setState(new SlaveState()); + } + } + } + } + + /** + * Default implementation for message handlers in any state. + * + * Individual states must override these if they want a behavior + * that differs from the default. + * + * In general, these handlers simply ignore the message and do + * nothing. + * + * There are some exceptions though, since some messages really + * are handled the same way in every state (e.g., ECHO_REQUST) or + * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY + */ + public abstract class OFSwitchHandshakeState { + + void processOFBarrierReply(OFBarrierReply m) { + // do nothing + } + + void processOFError(OFErrorMsg m) { + logErrorDisconnect(m); + } + + void processOFFlowRemoved(OFFlowRemoved m) { + unhandledMessageReceived(m); + } + + void processOFGetConfigReply(OFGetConfigReply m) { + // we only expect config replies in the WAIT_CONFIG_REPLY state + // TODO: might use two different strategies depending on whether + // we got a miss length of 64k or not. + illegalMessageReceived(m); + } + + void processOFPacketIn(OFPacketIn m) { + unhandledMessageReceived(m); + } + + // By default add port status messages to a pending list + void processOFPortStatus(OFPortStatus m) { + pendingPortStatusMsg.add(m); + } + + void processOFQueueGetConfigReply(OFQueueGetConfigReply m) { + unhandledMessageReceived(m); + } + + void processOFStatsReply(OFStatsReply m) { + switch(m.getStatsType()) { + case PORT_DESC: + processPortDescStatsReply((OFPortDescStatsReply) m); + break; + default: + unhandledMessageReceived(m); + } + } + + void processOFExperimenter(OFExperimenter m) { + if (m instanceof OFBsnControllerConnectionsReply) { + OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m; + handleControllerConnectionMessage(reply); + } else { + unhandledMessageReceived(m); + } + } + + void processPortDescStatsReply(OFPortDescStatsReply m) { + unhandledMessageReceived(m); + } + + void processOFRoleReply(OFRoleReply m) { + unhandledMessageReceived(m); + } + + private final boolean handshakeComplete; + OFSwitchHandshakeState(boolean handshakeComplete) { + this.handshakeComplete = handshakeComplete; + } + + void logState() { + if(log.isDebugEnabled()) + log.debug("[{}] - Switch Handshake - enter state {}", mainConnection.getDatapathId(), this.getClass().getSimpleName()); + } + + /** enter this state. Can initialize the handler, send + * the necessary messages, etc. + */ + void enterState(){ + } + + /** + * Is this a state in which the handshake has completed? + * @return true if the handshake is complete + */ + public boolean isHandshakeComplete() { + return handshakeComplete; + } + + /** + * Used to notify the WAIT OF AUX state that + * a new connection has been added + * @param connection + */ + public void auxConnectionOpened(IOFConnectionBackend connection) { + // Should only be handled in wait of aux + log.debug("[{}] - Switch Handshake - unhandled aux connection event", + getDpid()); + } + /** + * Get a string specifying the switch connection, state, and + * message received. To be used as message for SwitchStateException + * or log messages + * @param h The channel handler (to get switch information_ + * @param m The OFMessage that has just been received + * @param details A string giving more details about the exact nature + * of the problem. + * @return + */ + // needs to be protected because enum members are acutally subclasses + protected String getSwitchStateMessage(OFMessage m, + String details) { + return String.format("Switch: [%s], State: [%s], received: [%s]" + + ", details: %s", + getSwitchInfoString(), + this.toString(), + m.getType().toString(), + details); + } + + /** + * We have an OFMessage we didn't expect given the current state and + * we want to treat this as an error. + * We currently throw an exception that will terminate the connection + * However, we could be more forgiving + * @param h the channel handler that received the message + * @param m the message + * @throws SwitchStateExeption we always through the execption + */ + // needs to be protected because enum members are acutally subclasses + protected void illegalMessageReceived(OFMessage m) { + String msg = getSwitchStateMessage(m, + "Switch should never send this message in the current state"); + throw new SwitchStateException(msg); + + } + + /** + * We have an OFMessage we didn't expect given the current state and + * we want to ignore the message + * @param h the channel handler the received the message + * @param m the message + */ + protected void unhandledMessageReceived(OFMessage m) { + switchManagerCounters.unhandledMessage.increment(); + if (log.isDebugEnabled()) { + String msg = getSwitchStateMessage(m, + "Ignoring unexpected message"); + log.debug(msg); + } + } + + /** + * Log an OpenFlow error message from a switch + * @param error The error message + */ + @LogMessageDoc(level="ERROR", + message="Error {error type} {error code} from {switch} " + + "in state {state}", + explanation="The switch responded with an unexpected error" + + "to an OpenFlow message from the controller", + recommendation="This could indicate improper network operation. " + + "If the problem persists restarting the switch and " + + "controller may help." + ) + protected void logError(OFErrorMsg error) { + log.error("{} from switch {} in state {}", + new Object[] { + error.toString(), + getSwitchInfoString(), + this.toString()}); + } + + /** + * Log an OpenFlow error message from a switch and disconnect the + * channel + * @param error The error message + */ + protected void logErrorDisconnect(OFErrorMsg error) { + logError(error); + mainConnection.disconnect(); + } + + /** + * Extract the role from an OFVendor message. + * + * Extract the role from an OFVendor message if the message is a + * Nicira role reply. Otherwise return null. + * + * @param h The channel handler receiving the message + * @param vendorMessage The vendor message to parse. + * @return The role in the message if the message is a Nicira role + * reply, null otherwise. + */ + protected OFControllerRole extractNiciraRoleReply(OFMessage vendorMessage) { + if (!(vendorMessage instanceof OFNiciraControllerRoleReply)) + return null; + OFNiciraControllerRoleReply roleReply = + (OFNiciraControllerRoleReply) vendorMessage; + return NiciraRoleUtils.niciraToOFRole(roleReply); + } + + /** + * Handle a port status message. + * + * Handle a port status message by updating the port maps in the + * IOFSwitch instance and notifying Controller about the change so + * it can dispatch a switch update. + * + * @param h The OFChannelHhandler that received the message + * @param m The PortStatus message we received + * @param doNotify if true switch port changed events will be + * dispatched + */ + protected void handlePortStatusMessage(OFPortStatus m, + boolean doNotify) { + if (sw == null) { + String msg = getSwitchStateMessage(m, + "State machine error: switch is null. Should never " + + "happen"); + throw new SwitchStateException(msg); + } + Collection<PortChangeEvent> changes = sw.processOFPortStatus(m); + if (doNotify) { + for (PortChangeEvent ev: changes) + switchManager.notifyPortChanged(sw, ev.port, ev.type); + } + } + + protected void handleControllerConnectionMessage(OFBsnControllerConnectionsReply m) { + if (sw == null) { + String msg = getSwitchStateMessage(m, + "State machine error: switch is null. Should never " + + "happen"); + throw new SwitchStateException(msg); + } + // Update switches + sw.updateControllerConnections(m); + // Notify role manager + roleManager.notifyControllerConnectionUpdate(); + } + + + /** + * Process an OF message received on the channel and + * update state accordingly. + * + * The main "event" of the state machine. Process the received message, + * send follow up message if required and update state if required. + * + * Switches on the message type and calls more specific event handlers + * for each individual OF message type. If we receive a message that + * is supposed to be sent from a controller to a switch we throw + * a SwitchStateExeption. + * + * The more specific handlers can also throw SwitchStateExceptions + * + * @param h The OFChannelHandler that received the message + * @param m The message we received. + * @throws SwitchStateException + * @throws IOException + */ + void processOFMessage(OFMessage m) { + roleChanger.checkTimeout(); + switch(m.getType()) { + case BARRIER_REPLY: + processOFBarrierReply((OFBarrierReply)m); + break; + case ERROR: + processOFError((OFErrorMsg)m); + break; + case FLOW_REMOVED: + processOFFlowRemoved((OFFlowRemoved)m); + break; + case GET_CONFIG_REPLY: + processOFGetConfigReply((OFGetConfigReply)m); + break; + case PACKET_IN: + processOFPacketIn((OFPacketIn)m); + break; + case PORT_STATUS: + processOFPortStatus((OFPortStatus)m); + break; + case QUEUE_GET_CONFIG_REPLY: + processOFQueueGetConfigReply((OFQueueGetConfigReply)m); + break; + case STATS_REPLY: + processOFStatsReply((OFStatsReply)m); + break; + case ROLE_REPLY: + processOFRoleReply((OFRoleReply)m); + break; + case EXPERIMENTER: + processOFExperimenter((OFExperimenter)m); + break; + default: + illegalMessageReceived(m); + break; + } + } + } + + /** + * Initial state before channel is connected. Should not handle any messages. + */ + public class InitState extends OFSwitchHandshakeState { + + InitState() { + super(false); + } + + @Override + public void logState() { + log.debug("[{}] - Switch Handshake - Initiating from {}", + getDpid(), mainConnection.getRemoteInetAddress()); + } + } + + /** + * We are waiting for a features reply message. Once we receive it + * we send a SetConfig request, barrier, and GetConfig request. + * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY + */ + public class WaitPortDescStatsReplyState extends OFSwitchHandshakeState { + WaitPortDescStatsReplyState() { + super(false); + } + + @Override + void enterState(){ + sendPortDescRequest(); + } + + @Override + void processPortDescStatsReply(OFPortDescStatsReply m) { + portDescStats = m; + + setState(new WaitConfigReplyState()); + } + + @Override + void processOFExperimenter(OFExperimenter m) { + unhandledMessageReceived(m); + } + } + + public class WaitSetL2TableReplyState extends OFSwitchHandshakeState { + + WaitSetL2TableReplyState() { + super(false); + } + + @Override + void processOFExperimenter(OFExperimenter m) { + // TODO: actually parse the response + setState(new WaitConfigReplyState()); + }; + + @Override + void processOFStatsReply(OFStatsReply m) { + illegalMessageReceived(m); + } + } + + /** + * We are waiting for a config reply message. Once we receive it + * we send a DescriptionStatsRequest to the switch. + * Next state: WAIT_DESCRIPTION_STAT_REPLY + */ + public class WaitConfigReplyState extends OFSwitchHandshakeState { + + WaitConfigReplyState() { + super(false); + } + + @Override + @LogMessageDocs({ + @LogMessageDoc(level="WARN", + message="Config Reply from {switch} has " + + "miss length set to {length}", + explanation="The controller requires that the switch " + + "use a miss length of 0xffff for correct " + + "function", + recommendation="Use a different switch to ensure " + + "correct function") + }) + void processOFGetConfigReply(OFGetConfigReply m) { + if (m.getMissSendLen() == 0xffff) { + log.trace("Config Reply from switch {} confirms " + + "miss length set to 0xffff", + getSwitchInfoString()); + } else { + // FIXME: we can't really deal with switches that don't send + // full packets. Shouldn't we drop the connection here? + // FIXME: count?? + log.warn("Config Reply from switch {} has" + + "miss length set to {}", + getSwitchInfoString(), + m.getMissSendLen()); + } + setState(new WaitDescriptionStatReplyState()); + } + + @Override + void processOFStatsReply(OFStatsReply m) { + illegalMessageReceived(m); + } + + @Override + void processOFError(OFErrorMsg m) { + if ((m.getErrType() == OFErrorType.BAD_REQUEST) && + (((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.BAD_EXPERIMENTER)) { + log.debug("Switch {} has multiple tables but does not " + + "support L2 table extension", + getSwitchInfoString()); + return; + } + logErrorDisconnect(m); + } + + @Override + void enterState() { + sendHandshakeSetConfig(); + } + } + + /** + * We are waiting for a OFDescriptionStat message from the switch. + * Once we receive any stat message we try to parse it. If it's not + * a description stats message we disconnect. If its the expected + * description stats message, we: + * - use the switch driver to bind the switch and get an IOFSwitch + * instance, setup the switch instance + * - setup the IOFSwitch instance + * - add switch to FloodlightProvider and send the intial role + * request to the switch. + * + * Next state: WaitOFAuxCxnsReplyState (if OF1.3), else + * WaitInitialRoleState or WaitSwitchDriverSubHandshake + * + * All following states will have a h.sw instance! + */ + public class WaitDescriptionStatReplyState extends OFSwitchHandshakeState{ + + WaitDescriptionStatReplyState() { + super(false); + } + + @LogMessageDoc(message="Switch {switch info} bound to class " + + "{switch driver}, description {switch description}", + explanation="The specified switch has been bound to " + + "a switch driver based on the switch description" + + "received from the switch") + @Override + void processOFStatsReply(OFStatsReply m) { + // Read description, if it has been updated + if (m.getStatsType() != OFStatsType.DESC) { + illegalMessageReceived(m); + return; + } + + OFDescStatsReply descStatsReply = (OFDescStatsReply) m; + SwitchDescription description = new SwitchDescription(descStatsReply); + sw = switchManager.getOFSwitchInstance(mainConnection, description, factory, featuresReply.getDatapathId()); + switchManager.switchAdded(sw); + // set switch information + // set features reply and channel first so we a DPID and + // channel info. + sw.setFeaturesReply(featuresReply); + if(portDescStats != null) { + sw.setPortDescStats(portDescStats); + } + + // Handle pending messages now that we have a sw object + handlePendingPortStatusMessages(description); + + // Handle non OF 13 connections + if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){ + sw.startDriverHandshake(); + if (sw.isDriverHandshakeComplete()) { + setState(new WaitAppHandshakeState()); + } else { + setState(new WaitSwitchDriverSubHandshakeState()); + } + } + // Handle OF 1.3 MAIN Connection + else{ + setState(new WaitOFAuxCxnsReplyState()); + } + } + + void handlePendingPortStatusMessages(SwitchDescription description){ + for (OFPortStatus ps: pendingPortStatusMsg) + handlePortStatusMessage(ps, false); + pendingPortStatusMsg.clear(); + log.info("Switch {} bound to class {}," + + " description {}", + new Object[] { sw, sw.getClass(), + description }); + } + + @Override + void enterState() { + sendHandshakeDescriptionStatsRequest(); + } + } + + /** + * We are waiting for an OFAuxCxnsReply message from the switch. + * If the switch replies with a status of 0 it has approved of our request. + * If the auxiliary connections haven't already connected we will + * wait for them. + * + * Next state: WAIT_GENTABLE_DESC_STATS_REPLY (if OF1.3), else + * WAIT_INITIAL_ROLE or WAIT_SWITCH_DRIVER_SUB_HANDSHAKE + * + * All following states will have a h.sw instance! + */ + public class WaitOFAuxCxnsReplyState extends OFSwitchHandshakeState { + + // Default number of aux connections + int numAux = 0; + + WaitOFAuxCxnsReplyState() { + super(false); + } + + @Override + void processOFExperimenter(OFExperimenter m) { + if(m instanceof OFBsnSetAuxCxnsReply){ + OFBsnSetAuxCxnsReply auxReply = (OFBsnSetAuxCxnsReply) m; + + if(auxReply.getStatus() == 0){ + if(this.numAux != 0){ + // All aux connections havent arrived yet + if(auxConnections.size() != this.numAux){ + // We do nothing and wait for connections... + } else { + // Looks like all the aux connections have already arrived + gotoNextState(); + } + } + else { + // We don't need any OF Aux Connections + gotoNextState(); + } + } else { + String msg = String.format("Switch: [%s], HandshakeState: [%s], " + + "received unexpected OF Aux Status [%s]. ", + OFSwitchHandshakeHandler.this.getSwitchInfoString(), + OFSwitchHandshakeHandler.this.state.toString(), + String.valueOf(auxReply.getStatus())); + throw new OFAuxException(msg); + } + } else if(m instanceof OFBsnControllerConnectionsReply) { + OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m; + handleControllerConnectionMessage(reply); + } + } + + @Override + public void auxConnectionOpened(IOFConnectionBackend auxConnection){ + auxConnections.put(auxConnection.getAuxId(), auxConnection); + auxConnection.setListener(OFSwitchHandshakeHandler.this); + + // Only handle success case + if(auxConnections.size() == this.numAux){ + if(log.isDebugEnabled()) { + log.debug("[{}] - all {} required aux connections open. Proceeding", + getDpid(), numAux); + } + gotoNextState(); + } else { + log.debug("[" + getDpid() + "] - {} / {} required aux connections open. Waiting for more connections. ", + auxConnections.size(), numAux); + } + } + + @Override + void processOFError(OFErrorMsg m) { + log.info("Received error on OF Aux handshake - switch does not support OF Aux: {}", m); + gotoNextState(); + } + + void gotoNextState(){ + // Register any aux connections that have been receieved. + for (IOFConnectionBackend conn : auxConnections.values()) { + sw.registerConnection(conn); + } + setState(new WaitGentableDescStatsReplyState()); + } + + @Override + public void enterState() { + this.numAux = switchManager.getNumRequiredConnections(); + sendOFAuxSetCxnsRequest(this.numAux); + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + } + + /** + * We have requested the GenTable mapping (OFBsnGenTableDescStatsRequest) + * and are waiting on the reply / replies (note: it is a multipart message). + * Once we're received all parts, we create a GenTableMapping object and + * set it in the switch. + * + * If we receive an error messsage corresponding to our request, we conclude + * that the switch doesn't support GenTables and leave the empty default + * mapping in the switch. + * + * Next state: WaitSwitchDriverSubHandshakeState() if a driver handshake is required + * WaitAppHandshake else + */ + public class WaitGentableDescStatsReplyState extends OFSwitchHandshakeState { + + private final List<OFBsnGentableDescStatsReply> pendingGenTableDescStatsReplies; + private final long pendingRequestXid; + + WaitGentableDescStatsReplyState() { + super(false); + pendingGenTableDescStatsReplies = new CopyOnWriteArrayList<>(); + pendingRequestXid = sendHandshakeGenTableDescStatsRequest(); + } + + @Override + void processOFStatsReply(OFStatsReply m) { + // Read description, if it has been updated + if (!(m instanceof OFBsnGentableDescStatsReply)) { + illegalMessageReceived(m); + return; + } + + OFBsnGentableDescStatsReply reply = (OFBsnGentableDescStatsReply) m; + + pendingGenTableDescStatsReplies.add(reply); + if(reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { + // more replies to follow, stay in state + return; + } + + if(sw == null) { + throw new IllegalArgumentException("Switch instance unknown at time of GenTableDescStatsReply"); + } + + GenTableMap genTableMap = GenTableMap.of(pendingGenTableDescStatsReplies); + if(log.isDebugEnabled()) + log.debug("[{}] Gen Tables: {}", sw.getId(), genTableMap); + sw.setGenTableMap(genTableMap); + + gotoNextState(); + } + + public void gotoNextState() { + sw.startDriverHandshake(); + if (sw.isDriverHandshakeComplete()) + setState(new WaitAppHandshakeState()); + else + setState(new WaitSwitchDriverSubHandshakeState()); + } + + @Override + void processOFError(OFErrorMsg m) { + if(m.getXid() == pendingRequestXid) { + // let switch continue with an empty set of gentables + log.info("Received error on GenTable handshake - switch does not support gentables: {}", m); + gotoNextState(); + } else { + illegalMessageReceived(m); + } + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + } + + public class WaitSwitchDriverSubHandshakeState extends OFSwitchHandshakeState { + + WaitSwitchDriverSubHandshakeState() { + super(false); + } + + @Override + void processOFMessage(OFMessage m) { + // FIXME: other message to handle here? + sw.processDriverHandshakeMessage(m); + if (sw.isDriverHandshakeComplete()) { + setState(new WaitAppHandshakeState()); + } + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + } + + public class WaitAppHandshakeState extends OFSwitchHandshakeState { + + private final Iterator<IAppHandshakePluginFactory> pluginIterator; + private OFSwitchAppHandshakePlugin plugin; + + WaitAppHandshakeState() { + super(false); + this.pluginIterator = switchManager.getHandshakePlugins().iterator(); + } + + @Override + void processOFMessage(OFMessage m) { + if(m.getType() == OFType.PORT_STATUS){ + OFPortStatus status = (OFPortStatus) m; + handlePortStatusMessage(status, false); + } + else if(plugin != null){ + this.plugin.processOFMessage(m); + } + else{ + super.processOFMessage(m); + } + } + + /** + * Called by handshake plugins to signify that they have finished their + * sub handshake. + * + * @param result + * the result of the sub handshake + */ + void exitPlugin(PluginResult result) { + + // Proceed + if (result.getResultType() == PluginResultType.CONTINUE) { + if (log.isDebugEnabled()) { + log.debug("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}." + + " Proceeding normally..", + this.plugin.getClass().getSimpleName(), result); + } + + enterNextPlugin(); + + // Stop + } else if (result.getResultType() == PluginResultType.DISCONNECT) { + log.error("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. " + + "Disconnecting switch.", + this.plugin.getClass().getSimpleName(), result); + mainConnection.disconnect(); + } else if (result.getResultType() == PluginResultType.QUARANTINE) { + log.warn("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. " + + "Putting switch into quarantine state.", + this.plugin.getClass().getSimpleName(), + result); + setState(new QuarantineState(result.getReason())); + } + } + + @Override + public void enterState() { + enterNextPlugin(); + } + + /** + * Initialize the plugin and begin. + * + * @param plugin the of switch app handshake plugin + */ + public void enterNextPlugin() { + if(this.pluginIterator.hasNext()){ + this.plugin = pluginIterator.next().createPlugin(); + this.plugin.init(this, sw, timer); + this.plugin.enterPlugin(); + } + // No more plugins left... + else{ + // Non OF 1.3 + if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){ + setState(new WaitInitialRoleState()); + } else { + setState(new WaitControllerCxnsReplyState()); + } + } + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + + OFSwitchAppHandshakePlugin getCurrentPlugin() { + return plugin; + } + + } + + /** + * Switch is in a quarantine state. Essentially the handshake is complete. + */ + public class QuarantineState extends OFSwitchHandshakeState { + + private final String quarantineReason; + + QuarantineState(String reason) { + super(true); + this.quarantineReason = reason; + } + + @Override + public void enterState() { + setSwitchStatus(SwitchStatus.QUARANTINED); + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + + public String getQuarantineReason() { + return this.quarantineReason; + } + } + + public class WaitControllerCxnsReplyState extends OFSwitchHandshakeState { + + WaitControllerCxnsReplyState() { + super(false); + } + + @Override + void processOFExperimenter(OFExperimenter m) { + if(m instanceof OFBsnControllerConnectionsReply) { + OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m; + handleControllerConnectionMessage(reply); + + setState(new WaitInitialRoleState()); + } else { + unhandledMessageReceived(m); + } + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + + @Override + public void enterState() { + // Write out request down + OFBsnControllerConnectionsRequest request = factory.buildBsnControllerConnectionsRequest() + .build(); + mainConnection.write(request); + + } + + } + + /** + * We are waiting for the initial role reply message (or error indication) + * from the switch. Next State: MASTER or SLAVE + */ + public class WaitInitialRoleState extends OFSwitchHandshakeState { + + WaitInitialRoleState() { + super(false); + } + + @Override + void processOFError(OFErrorMsg m) { + // role changer will ignore the error if it isn't for it + boolean didHandle = roleChanger.deliverError(m); + if (!didHandle) { + logError(m); + } + } + + @Override + void processOFExperimenter(OFExperimenter m) { + OFControllerRole role = extractNiciraRoleReply(m); + // If role == null it measn the message wasn't really a + // Nicira role reply. We ignore this case. + if (role != null) { + roleChanger.deliverRoleReply(m.getXid(), role); + } else if(m instanceof OFBsnControllerConnectionsReply) { + OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m; + handleControllerConnectionMessage(reply); + } else { + unhandledMessageReceived(m); + } + } + + @Override + void processOFRoleReply(OFRoleReply m) { + roleChanger.deliverRoleReply(m.getXid(), m.getRole()); + } + + @Override + void processOFStatsReply(OFStatsReply m) { + illegalMessageReceived(m); + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, false); + } + + @Override + void enterState(){ + sendRoleRequest(roleManager.getOFControllerRole()); + } + } + + /** + * The switch is in MASTER role. We enter this state after a role + * reply from the switch is received (or the controller is MASTER + * and the switch doesn't support roles). The handshake is complete at + * this point. We only leave this state if the switch disconnects or + * if we send a role request for SLAVE /and/ receive the role reply for + * SLAVE. + */ + public class MasterState extends OFSwitchHandshakeState { + + MasterState() { + super(true); + } + + @Override + void enterState() { + setSwitchStatus(SwitchStatus.MASTER); + } + + @LogMessageDoc(level="WARN", + message="Received permission error from switch {} while" + + "being master. Reasserting master role.", + explanation="The switch has denied an operation likely " + + "indicating inconsistent controller roles", + recommendation="This situation can occurs transiently during role" + + " changes. If, however, the condition persists or happens" + + " frequently this indicates a role inconsistency. " + + LogMessageDoc.CHECK_CONTROLLER ) + @Override + void processOFError(OFErrorMsg m) { + // role changer will ignore the error if it isn't for it + boolean didHandle = roleChanger.deliverError(m); + if (didHandle) + return; + if ((m.getErrType() == OFErrorType.BAD_REQUEST) && + (((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.EPERM)) { + // We are the master controller and the switch returned + // a permission error. This is a likely indicator that + // the switch thinks we are slave. Reassert our + // role + // FIXME: this could be really bad during role transitions + // if two controllers are master (even if its only for + // a brief period). We might need to see if these errors + // persist before we reassert + switchManagerCounters.epermErrorWhileSwitchIsMaster.increment(); + log.warn("Received permission error from switch {} while" + + "being master. Reasserting master role.", + getSwitchInfoString()); + reassertRole(OFControllerRole.ROLE_MASTER); + } + else if ((m.getErrType() == OFErrorType.FLOW_MOD_FAILED) && + (((OFFlowModFailedErrorMsg)m).getCode() == OFFlowModFailedCode.ALL_TABLES_FULL)) { + sw.setTableFull(true); + } + else { + logError(m); + } + dispatchMessage(m); + } + + @Override + void processOFExperimenter(OFExperimenter m) { + OFControllerRole role = extractNiciraRoleReply(m); + // If role == null it means the message wasn't really a + // Nicira role reply. We ignore just dispatch it to the + // OFMessage listenersa in this case. + if (role != null) { + roleChanger.deliverRoleReply(m.getXid(), role); + } else if (m instanceof OFBsnControllerConnectionsReply){ + OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m; + handleControllerConnectionMessage(reply); + } else { + dispatchMessage(m); + } + } + + + @Override + void processOFRoleReply(OFRoleReply m) { + roleChanger.deliverRoleReply(m.getXid(), m.getRole()); + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, true); + } + + @Override + void processOFPacketIn(OFPacketIn m) { + dispatchMessage(m); + } + + @Override + void processOFFlowRemoved(OFFlowRemoved m) { + dispatchMessage(m); + } + } + + /** + * The switch is in SLAVE role. We enter this state after a role + * reply from the switch is received. The handshake is complete at + * this point. We only leave this state if the switch disconnects or + * if we send a role request for MASTER /and/ receive the role reply for + * MASTER. + * TODO: CURRENTLY, WE DO NOT DISPATCH ANY MESSAGE IN SLAVE. + */ + public class SlaveState extends OFSwitchHandshakeState { + + SlaveState() { + super(true); + } + + @Override + void enterState() { + setSwitchStatus(SwitchStatus.SLAVE); + } + + @Override + void processOFError(OFErrorMsg m) { + // role changer will ignore the error if it isn't for it + boolean didHandle = roleChanger.deliverError(m); + if (!didHandle) { + logError(m); + } + } + + @Override + void processOFStatsReply(OFStatsReply m) { + } + + @Override + void processOFPortStatus(OFPortStatus m) { + handlePortStatusMessage(m, true); + } + + @Override + void processOFExperimenter(OFExperimenter m) { + OFControllerRole role = extractNiciraRoleReply(m); + // If role == null it means the message wasn't really a + // Nicira role reply. We ignore it. + if (role != null) { + roleChanger.deliverRoleReply(m.getXid(), role); + } else if (m instanceof OFBsnControllerConnectionsReply){ + OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m; + handleControllerConnectionMessage(reply); + } else { + unhandledMessageReceived(m); + } + } + + @Override + void processOFRoleReply(OFRoleReply m) { + roleChanger.deliverRoleReply(m.getXid(), m.getRole()); + } + + @Override + @LogMessageDoc(level="WARN", + message="Received PacketIn from switch {} while" + + "being slave. Reasserting slave role.", + explanation="The switch has receive a PacketIn despite being " + + "in slave role indicating inconsistent controller roles", + recommendation="This situation can occurs transiently during role" + + " changes. If, however, the condition persists or happens" + + " frequently this indicates a role inconsistency. " + + LogMessageDoc.CHECK_CONTROLLER ) + void processOFPacketIn(OFPacketIn m) { + // we don't expect packetIn while slave, reassert we are slave + switchManagerCounters.packetInWhileSwitchIsSlave.increment(); + log.warn("Received PacketIn from switch {} while" + + "being slave. Reasserting slave role.", sw); + reassertRole(OFControllerRole.ROLE_SLAVE); + } + }; + + + /** + * Create a new unconnected OFChannelHandler. + * @param controller + * @param broker + * @throws SwitchHandshakeHandlerException + */ + OFSwitchHandshakeHandler(@Nonnull IOFConnectionBackend connection, + @Nonnull OFFeaturesReply featuresReply, + @Nonnull IOFSwitchManager switchManager, + @Nonnull RoleManager roleManager, + @Nonnull Timer timer) { + Preconditions.checkNotNull(connection, "connection"); + Preconditions.checkNotNull(featuresReply, "featuresReply"); + Preconditions.checkNotNull(switchManager, "switchManager"); + Preconditions.checkNotNull(roleManager, "roleManager"); + Preconditions.checkNotNull(timer, "timer"); + Preconditions.checkArgument(connection.getAuxId().equals(OFAuxId.MAIN), + "connection must be MAIN connection but is %s", connection); + + this.switchManager = switchManager; + this.roleManager = roleManager; + this.mainConnection = connection; + this.auxConnections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>(); + this.featuresReply = featuresReply; + this.timer = timer; + this.switchManagerCounters = switchManager.getCounters(); + this.factory = OFFactories.getFactory(featuresReply.getVersion()); + this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_NS); + setState(new InitState()); + this.pendingPortStatusMsg = new ArrayList<OFPortStatus>(); + + connection.setListener(this); + } + + /** + * This begins the switch handshake. We start where the OFChannelHandler + * left off, right after receiving the OFFeaturesReply. + */ + public void beginHandshake() { + Preconditions.checkState(state instanceof InitState, "must be in InitState"); + + if (this.featuresReply.getNTables() > 1) { + log.debug("Have {} table for switch {}", this.featuresReply.getNTables(), + getSwitchInfoString()); + // likely supports L2 table extensions. Send set + sendHandshakeL2TableSet(); + // TODO: no L2 SET reply yet, so fire and forget the set + } + + if(this.featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) { + setState(new WaitConfigReplyState()); + } else { + // OF 1.3. Ask for Port Descriptions + setState(new WaitPortDescStatsReplyState()); + } + } + + public DatapathId getDpid(){ + return this.featuresReply.getDatapathId(); + } + + public OFAuxId getOFAuxId(){ + return this.featuresReply.getAuxiliaryId(); + } + + /** + * Is this a state in which the handshake has completed? + * @return true if the handshake is complete + */ + public boolean isHandshakeComplete() { + return this.state.isHandshakeComplete(); + } + + /** + * Forwards to RoleChanger. See there. + * @param role + */ + void sendRoleRequestIfNotPending(OFControllerRole role) { + try { + roleChanger.sendRoleRequestIfNotPending(role); + } catch (IOException e) { + log.error("Disconnecting switch {} due to IO Error: {}", + getSwitchInfoString(), e.getMessage()); + mainConnection.disconnect(); + } + } + + + /** + * Forwards to RoleChanger. See there. + * @param role + */ + void sendRoleRequest(OFControllerRole role) { + try { + roleChanger.sendRoleRequest(role); + } catch (IOException e) { + log.error("Disconnecting switch {} due to IO Error: {}", + getSwitchInfoString(), e.getMessage()); + mainConnection.disconnect(); + } + } + + /** + * Dispatches the message to the controller packet pipeline + */ + private void dispatchMessage(OFMessage m) { + this.switchManager.handleMessage(this.sw, m, null); + } + + /** + * Return a string describing this switch based on the already available + * information (DPID and/or remote socket) + * @return + */ + private String getSwitchInfoString() { + if (sw != null) + return sw.toString(); + String channelString; + if (mainConnection == null || mainConnection.getRemoteInetAddress() == null) { + channelString = "?"; + } else { + channelString = mainConnection.getRemoteInetAddress().toString(); + } + String dpidString; + if (featuresReply == null) { + dpidString = "?"; + } else { + dpidString = featuresReply.getDatapathId().toString(); + } + return String.format("[%s DPID[%s]]", channelString, dpidString); + } + + /** + * Update the channels state. Only called from the state machine. + * TODO: enforce restricted state transitions + * @param state + */ + private void setState(OFSwitchHandshakeState state) { + this.state = state; + state.logState(); + state.enterState(); + } + + private void sendOFAuxSetCxnsRequest(int numAux) { + OFBsnSetAuxCxnsRequest request = factory.buildBsnSetAuxCxnsRequest() + .setNumAux(numAux) + .build(); + mainConnection.write(request); + } + + public void processOFMessage(OFMessage m) { + state.processOFMessage(m); + } + + /** + * Send the configuration requests to tell the switch we want full + * packets + * @throws IOException + */ + private void sendHandshakeSetConfig() { + // Ensure we receive the full packet via PacketIn + // FIXME: We don't set the reassembly flags. + OFSetConfig configSet = factory.buildSetConfig() + .setXid(handshakeTransactionIds--) + .setMissSendLen(0xffff) + .build(); + + // Barrier + OFBarrierRequest barrier = factory.buildBarrierRequest() + .setXid(handshakeTransactionIds--) + .build(); + + // Verify (need barrier?) + OFGetConfigRequest configReq = factory.buildGetConfigRequest() + .setXid(handshakeTransactionIds--) + .build(); + List<OFMessage> msgList = ImmutableList.<OFMessage>of(configSet, barrier, configReq); + mainConnection.write(msgList); + } + + protected void sendPortDescRequest() { + mainConnection.write(factory.portDescStatsRequest(ImmutableSet.<OFStatsRequestFlags>of())); + } + + /** + * send a description state request + */ + private void sendHandshakeDescriptionStatsRequest() { + // Send description stats request to set switch-specific flags + OFDescStatsRequest descStatsRequest = factory.buildDescStatsRequest() + .setXid(handshakeTransactionIds--) + .build(); + mainConnection.write(descStatsRequest); + } + + /** send a BSN GenTable DescStats Request, querying for the tables + * available at the switch. + * @return + */ + private long sendHandshakeGenTableDescStatsRequest() { + long xid = handshakeTransactionIds--; + OFBsnGentableDescStatsRequest descStatsRequest = factory.buildBsnGentableDescStatsRequest() + .setXid(xid) + .build(); + + mainConnection.write(descStatsRequest); + return xid; + } + + //TODO: Can we nuke this? - jason + /** + * Send an setL2TableSet message to the switch. + */ + private void sendHandshakeL2TableSet() { + // The BsnSetL2Table message is only supported in OF 1.0, so skip if + // we're using a later version + if (factory.getVersion() != OFVersion.OF_10) + return; + + OFBsnSetL2TableRequest m = factory.buildBsnSetL2TableRequest() + .setXid(handshakeTransactionIds--) + .setL2TableEnable(true) + .setL2TablePriority(1000) + .build(); + mainConnection.write(m); + } + + OFSwitchHandshakeState getStateForTesting() { + return state; + } + + void reassertRole(OFControllerRole role){ + this.roleManager.reassertRole(this, HARole.ofOFRole(role)); + } + + void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) { + roleChanger = new RoleChanger(TimeUnit.MILLISECONDS.toNanos(roleTimeoutMs)); + } + + /** + * Called by the switch manager when new aux connections have connected. + * This alerts the state machine of an aux connection. + * + * @param connection + * the aux connection + */ + public synchronized void auxConnectionOpened(IOFConnectionBackend connection) { + if(log.isDebugEnabled()) + log.debug("[{}] - Switch Handshake - new aux connection {}", + this.getDpid(), connection.getAuxId()); + this.state.auxConnectionOpened(connection); + } + + /** + * Gets the main connection + * + * @return the main connection + */ + public IOFConnectionBackend getMainConnection() { + return this.mainConnection; + } + + /** + * Determines if this handshake handler is responsible for the supplied + * connection. + * + * @param connection + * an OF connection + * @return true if the handler has the connection + */ + public boolean hasConnection(IOFConnectionBackend connection) { + if (this.mainConnection.equals(connection) + || this.auxConnections.get(connection.getAuxId()) == connection) { + return true; + } else { + return false; + } + } + + void cleanup() { + for (IOFConnectionBackend conn : this.auxConnections.values()) { + conn.disconnect(); + } + + this.mainConnection.disconnect(); + } + + public String getState() { + return this.state.getClass().getSimpleName(); + } + + public String getQuarantineReason() { + if(this.state instanceof QuarantineState) { + QuarantineState qs = (QuarantineState) this.state; + return qs.getQuarantineReason(); + } + return null; + } + + /** + * Gets the current connections that this switch handshake handler is + * responsible for. Used primarily by the REST API. + * @return an immutable list of IOFConnections + */ + public ImmutableList<IOFConnection> getConnections() { + ImmutableList.Builder<IOFConnection> builder = ImmutableList.builder(); + + builder.add(mainConnection); + builder.addAll(auxConnections.values()); + + return builder.build(); + } + + + /** IOFConnectionListener */ + @Override + public void connectionClosed(IOFConnectionBackend connection) { + // Disconnect handler's remaining connections + cleanup(); + + // Only remove the switch handler when the main connection is + // closed + if (connection == this.mainConnection) { + switchManager.handshakeDisconnected(connection.getDatapathId()); + if(sw != null) { + log.debug("[{}] - main connection {} closed - disconnecting switch", + connection); + + setSwitchStatus(SwitchStatus.DISCONNECTED); + switchManager.switchDisconnected(sw); + } + } + } + + @Override + public void messageReceived(IOFConnectionBackend connection, OFMessage m) { + processOFMessage(m); + } + + @Override + public boolean isSwitchHandshakeComplete(IOFConnectionBackend connection) { + return state.isHandshakeComplete(); + } + + public void setSwitchStatus(SwitchStatus status) { + if(sw != null) { + SwitchStatus oldStatus = sw.getStatus(); + if(oldStatus != status) { + sw.setStatus(status); + switchManager.switchStatusChanged(sw, oldStatus, status); + } else { + log.warn("[{}] SwitchStatus change to {} requested, switch is already in status", + mainConnection.getDatapathId()); + } + } else { + log.warn("[{}] SwitchStatus change to {} requested, but switch is not allocated yet", + mainConnection.getDatapathId()); + } + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java deleted file mode 100644 index 51dfddc1a1625f530610f7ab00d407d57c9a9e70..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -/** -* Copyright 2012, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import org.openflow.protocol.statistics.OFDescriptionStatistics; - -import net.floodlightcontroller.core.OFSwitchBase; - -/** - * This is the internal representation of an openflow switch. - */ -public class OFSwitchImpl extends OFSwitchBase { - - @Override - @JsonIgnore - public void setSwitchProperties(OFDescriptionStatistics description) { - this.description = new OFDescriptionStatistics(description); - } - - @Override - public OFPortType getPortType(short port_num) { - return OFPortType.NORMAL; - } - - @Override - @JsonIgnore - public boolean isFastPort(short port_num) { - return false; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java new file mode 100644 index 0000000000000000000000000000000000000000..dd1cc86b7566655479c0f87234da9c33f6ed370e --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java @@ -0,0 +1,756 @@ +package net.floodlightcontroller.core.internal; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.channel.group.ChannelGroup; +import org.jboss.netty.channel.group.DefaultChannelGroup; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; + +import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.HAListenerTypeMarker; +import net.floodlightcontroller.core.HARole; +import net.floodlightcontroller.core.IFloodlightProviderService; +import net.floodlightcontroller.core.IHAListener; +import net.floodlightcontroller.core.IOFConnectionBackend; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.IOFSwitch.SwitchStatus; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.IOFSwitchDriver; +import net.floodlightcontroller.core.IOFSwitchListener; +import net.floodlightcontroller.core.LogicalOFMessageCategory; +import net.floodlightcontroller.core.PortChangeType; +import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.core.annotations.LogMessageDoc; +import net.floodlightcontroller.core.annotations.LogMessageDocs; +import net.floodlightcontroller.core.internal.Controller.IUpdate; +import net.floodlightcontroller.core.internal.Controller.ModuleLoaderState; +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.core.rest.SwitchRepresentation; +import net.floodlightcontroller.debugcounter.IDebugCounterService; +import net.floodlightcontroller.debugevent.IDebugEventService; +import net.floodlightcontroller.debugevent.IDebugEventService.EventType; +import net.floodlightcontroller.debugevent.IEventCategory; +import net.floodlightcontroller.debugevent.MockDebugEventService; + +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFAuxId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * The Switch Manager class contains most of the code involved with dealing + * with switches. The Switch manager keeps track of the switches known to the controller, + * their status, and any important information about the switch lifecycle. The + * Switch Manager also provides the switch service, which allows other modules + * to hook in switch listeners and get basic access to switch information. + * + * @author gregor, capveg, sovietaced + * + */ +public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListener, IHAListener, IFloodlightModule, IOFSwitchService { + private static final Logger log = LoggerFactory.getLogger(OFSwitchManager.class); + + private volatile OFControllerRole role; + private SwitchManagerCounters counters; + + private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers; + private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches; + + private ISwitchDriverRegistry driverRegistry; + + private Set<LogicalOFMessageCategory> logicalOFMessageCategories = new CopyOnWriteArraySet<LogicalOFMessageCategory>(); + private final List<IAppHandshakePluginFactory> handshakePlugins = new CopyOnWriteArrayList<IAppHandshakePluginFactory>(); + private int numRequiredConnections = -1; + // Event IDs for debug events + protected IEventCategory<SwitchEvent> evSwitch; + + // ISwitchService + protected Set<IOFSwitchListener> switchListeners; + + // Module Dependencies + IFloodlightProviderService floodlightProvider; + IDebugEventService debugEventService; + IDebugCounterService debugCounterService; + + /** IHAListener Implementation **/ + @Override + public void transitionToActive() { + this.role = HARole.ACTIVE.getOFRole(); + } + + @Override + public void transitionToStandby() { + this.role = HARole.STANDBY.getOFRole(); + } + + /** IOFSwitchManager Implementation **/ + + @Override public SwitchManagerCounters getCounters() { + return this.counters; + } + + private void addUpdateToQueue(IUpdate iUpdate) { + floodlightProvider.addUpdateToQueue(iUpdate); + } + + @Override + public synchronized void switchAdded(IOFSwitchBackend sw) { + DatapathId dpid = sw.getId(); + IOFSwitchBackend oldSw = this.switches.put(dpid, sw); + // Update event history + evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected")); + + if (oldSw == sw) { + // Note == for object equality, not .equals for value + counters.errorActivatedSwitchNotPresent + .increment(); + log.error("Switch {} added twice?", sw); + return; + } else if (oldSw != null) { + // This happens either when we have switches with duplicate + // DPIDs or when a switch reconnects before we saw the + // disconnect + counters.switchWithSameDpidActivated + .increment(); + log.warn("New switch added {} for already-added switch {}", sw, oldSw); + // We need to disconnect and remove the old switch + // TODO: we notify switch listeners that the switch has been + // removed and then we notify them that the new one has been + // added. One could argue that a switchChanged notification + // might be more appropriate in this case.... + oldSw.cancelAllPendingRequests(); + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); + oldSw.disconnect(); + } + + } + + @LogMessageDocs({ + @LogMessageDoc(level="ERROR", + message="Switch {switch} activated but was already active", + explanation="A switch that was already activated was " + + "activated again. This should not happen.", + recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG + ), + @LogMessageDoc(level="WARN", + message="New switch added {switch} for already-added switch {switch}", + explanation="A switch with the same DPID as another switch " + + "connected to the controller. This can be caused by " + + "multiple switches configured with the same DPID, or " + + "by a switch reconnected very quickly after " + + "disconnecting.", + recommendation="If this happens repeatedly, it is likely there " + + "are switches with duplicate DPIDs on the network. " + + "Reconfigure the appropriate switches. If it happens " + + "very rarely, then it is likely this is a transient " + + "network problem that can be ignored." + ) + }) + @Override + public synchronized void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) { + DatapathId dpid = sw.getId(); + IOFSwitchBackend presentSw = this.switches.get(dpid); + + if (presentSw != sw) { + // Note == for object equality, not .equals for value + counters.errorActivatedSwitchNotPresent + .increment(); + log.warn("Switch {} status change but not present in sync manager", sw); + return; + } + evSwitch.newEventWithFlush(new SwitchEvent(dpid, + String.format("%s -> %s", + oldStatus, + newStatus))); + + if(newStatus == SwitchStatus.MASTER && role != OFControllerRole.ROLE_MASTER) { + counters.invalidSwitchActivatedWhileSlave.increment(); + log.error("Switch {} activated but controller not MASTER", sw); + sw.disconnect(); + return; // only react to switch connections when master + } + + if(!oldStatus.isVisible() && newStatus.isVisible()) { + // the switch has just become visible. Send 'add' notification to our + // listeners + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED)); + } else if((oldStatus.isVisible() && !newStatus.isVisible())) { + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); + } + + // note: no else if - both may be true + if(oldStatus != SwitchStatus.MASTER && newStatus == SwitchStatus.MASTER ) { + counters.switchActivated.increment(); + addUpdateToQueue(new SwitchUpdate(dpid, + SwitchUpdateType.ACTIVATED)); + } else if(oldStatus == SwitchStatus.MASTER && newStatus != SwitchStatus.MASTER ) { + counters.switchDeactivated.increment(); + addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.DEACTIVATED)); + } + } + + @Override + public synchronized void switchDisconnected(IOFSwitchBackend sw) { + DatapathId dpid = sw.getId(); + IOFSwitchBackend presentSw = this.switches.get(dpid); + + if (presentSw != sw) { + // Note == for object equality, not .equals for value + counters.errorActivatedSwitchNotPresent + .increment(); + log.warn("Switch {} disconnect but not present in sync manager", sw); + return; + } + + counters.switchDisconnected.increment(); + this.switches.remove(dpid); + } + + @Override public void handshakeDisconnected(DatapathId dpid) { + this.switchHandlers.remove(dpid); + } + + public Iterable<IOFSwitch> getActiveSwitches() { + ImmutableList.Builder<IOFSwitch> builder = ImmutableList.builder(); + for(IOFSwitch sw: switches.values()) { + if(sw.getStatus().isControllable()) + builder.add(sw); + } + return builder.build(); + } + + public Map<DatapathId, IOFSwitch> getAllSwitchMap(boolean showInvisible) { + if(showInvisible) { + return ImmutableMap.<DatapathId, IOFSwitch>copyOf(switches); + } else { + ImmutableMap.Builder<DatapathId, IOFSwitch> builder = ImmutableMap.builder(); + for(IOFSwitch sw: switches.values()) { + if(sw.getStatus().isVisible()) + builder.put(sw.getId(), sw); + } + return builder.build(); + } + } + + @Override + public Map<DatapathId, IOFSwitch> getAllSwitchMap() { + return getAllSwitchMap(true); + } + + @Override + public Set<DatapathId> getAllSwitchDpids() { + return getAllSwitchMap().keySet(); + } + + public Set<DatapathId> getAllSwitchDpids(boolean showInvisible) { + return getAllSwitchMap(showInvisible).keySet(); + } + + @Override + public IOFSwitch getSwitch(DatapathId dpid) { + return this.switches.get(dpid); + } + + @Override + public IOFSwitch getActiveSwitch(DatapathId dpid) { + IOFSwitchBackend sw = this.switches.get(dpid); + if(sw != null && sw.getStatus().isVisible()) + return sw; + else + return null; + } + + enum SwitchUpdateType { + ADDED, + REMOVED, + ACTIVATED, + DEACTIVATED, + PORTCHANGED, + OTHERCHANGE + } + + /** + * Update message indicating a switch was added or removed + */ + class SwitchUpdate implements IUpdate { + private final DatapathId swId; + private final SwitchUpdateType switchUpdateType; + private final OFPortDesc port; + private final PortChangeType changeType; + + public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType) { + this(swId, switchUpdateType, null, null); + } + + public SwitchUpdate(DatapathId swId, + SwitchUpdateType switchUpdateType, + OFPortDesc port, + PortChangeType changeType) { + if (switchUpdateType == SwitchUpdateType.PORTCHANGED) { + if (port == null) { + throw new NullPointerException("Port must not be null " + + "for PORTCHANGED updates"); + } + if (changeType == null) { + throw new NullPointerException("ChangeType must not be " + + "null for PORTCHANGED updates"); + } + } else { + if (port != null || changeType != null) { + throw new IllegalArgumentException("port and changeType " + + "must be null for " + switchUpdateType + + " updates"); + } + } + this.swId = swId; + this.switchUpdateType = switchUpdateType; + this.port = port; + this.changeType = changeType; + } + + @Override + public void dispatch() { + if (log.isTraceEnabled()) { + log.trace("Dispatching switch update {} {}", swId, switchUpdateType); + } + if (switchListeners != null) { + for (IOFSwitchListener listener : switchListeners) { + switch(switchUpdateType) { + case ADDED: + // don't count here. We have more specific + // counters before the update is created + listener.switchAdded(swId); + break; + case REMOVED: + // don't count here. We have more specific + // counters before the update is created + listener.switchRemoved(swId); + break; + case PORTCHANGED: + counters.switchPortChanged + .increment(); + listener.switchPortChanged(swId, port, changeType); + break; + case ACTIVATED: + // don't count here. We have more specific + // counters before the update is created + listener.switchActivated(swId); + break; + case DEACTIVATED: + // ignore + break; + case OTHERCHANGE: + counters.switchOtherChange + .increment(); + listener.switchChanged(swId); + break; + } + } + } + } + } + + /** + * Handles a new OF Connection + * @param IOFConnectionBackend connection an opened OF Connection + * @param OFFeaturesReply featuresReply the features reply received for the opened connection. + * It is needed for the rest of the switch handshake. + */ + @Override + public void connectionOpened(IOFConnectionBackend connection, + OFFeaturesReply featuresReply) { + DatapathId dpid = connection.getDatapathId(); + OFAuxId auxId = connection.getAuxId(); + + log.debug("{} opened", connection); + + if(auxId.equals(OFAuxId.MAIN)) { + + // Create a new switch handshake handler + OFSwitchHandshakeHandler handler = + new OFSwitchHandshakeHandler(connection, featuresReply, this, + floodlightProvider.getRoleManager(), floodlightProvider.getTimer()); + + OFSwitchHandshakeHandler oldHandler = switchHandlers.put(dpid, handler); + + // Disconnect all the handler's connections + if(oldHandler != null){ + log.debug("{} is a new main connection, killing old handler connections", + connection); + oldHandler.cleanup(); + } + + handler.beginHandshake(); + + } else { + OFSwitchHandshakeHandler handler = switchHandlers.get(dpid); + + if(handler != null) { + handler.auxConnectionOpened(connection); + } + // Connections have arrived before the switchhandler is ready + else { + log.warn("{} arrived before main connection, closing connection", connection); + connection.disconnect(); + } + } + } + + @Override + public void addSwitchEvent(DatapathId dpid, String reason, boolean flushNow) { + if (flushNow) + evSwitch.newEventWithFlush(new SwitchEvent(dpid, reason)); + else + evSwitch.newEventNoFlush(new SwitchEvent(dpid, reason)); + } + + @Override + public synchronized void notifyPortChanged(IOFSwitchBackend sw, + OFPortDesc port, + PortChangeType changeType) { + Preconditions.checkNotNull(sw, "switch must not be null"); + Preconditions.checkNotNull(port, "port must not be null"); + Preconditions.checkNotNull(changeType, "changeType must not be null"); + + if (role != OFControllerRole.ROLE_MASTER) { + counters.invalidPortsChanged.increment(); + return; + } + if (!this.switches.containsKey(sw.getId())) { + counters.invalidPortsChanged.increment(); + return; + } + + if(sw.getStatus().isVisible()) { + // no need to count here. SwitchUpdate.dispatch will count + // the portchanged + SwitchUpdate update = new SwitchUpdate(sw.getId(), + SwitchUpdateType.PORTCHANGED, + port, changeType); + addUpdateToQueue(update); + } + } + + @Override + public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, + SwitchDescription description, + OFFactory factory, DatapathId datapathId) { + return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId); + } + + @Override + public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) { + floodlightProvider.handleMessage(sw, m, bContext); + } + + @Override + public void addOFSwitchDriver(String manufacturerDescriptionPrefix, + IOFSwitchDriver driver) { + this.driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver); + } + + @Override + public ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers() { + return ImmutableList.copyOf(this.switchHandlers.values()); + } + + @Override + public int getNumRequiredConnections() { + Preconditions.checkState(numRequiredConnections >= 0, "numRequiredConnections not calculated"); + return numRequiredConnections; + } + + public Set<LogicalOFMessageCategory> getLogicalOFMessageCategories() { + return logicalOFMessageCategories; + } + + private int calcNumRequiredConnections() { + if(!this.logicalOFMessageCategories.isEmpty()){ + // We use tree set here to maintain ordering + TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>(); + + for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){ + auxConnections.add(category.getAuxId()); + } + + OFAuxId first = auxConnections.first(); + OFAuxId last = auxConnections.last(); + + // Check for contiguous set (1....size()) + if(first.equals(OFAuxId.MAIN)) { + if(last.getValue() != auxConnections.size() - 1){ + throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)"); + } + return auxConnections.size() - 1; + } else if(first.equals(OFAuxId.of(1))) { + if(last.getValue() != auxConnections.size()){ + throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)"); + } + return auxConnections.size(); + } else { + throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1"); + } + } else { + return 0; + } + } + + /** ISwitchService Implementation **/ + @Override + public void addOFSwitchListener(IOFSwitchListener listener) { + this.switchListeners.add(listener); + } + + @Override + public void removeOFSwitchListener(IOFSwitchListener listener) { + this.switchListeners.remove(listener); + } + + @Override + public void registerLogicalOFMessageCategory(LogicalOFMessageCategory category) { + logicalOFMessageCategories.add(category); + } + + @Override + public boolean isCategoryRegistered(LogicalOFMessageCategory category) { + return logicalOFMessageCategories.contains(category); + } + + @Override + public SwitchRepresentation getSwitchRepresentation(DatapathId dpid) { + IOFSwitch sw = this.switches.get(dpid); + OFSwitchHandshakeHandler handler = this.switchHandlers.get(dpid); + + if(sw != null && handler != null) { + return new SwitchRepresentation(sw, handler); + } + return null; + } + + @Override + public List<SwitchRepresentation> getSwitchRepresentations() { + + List<SwitchRepresentation> representations = new ArrayList<SwitchRepresentation>(); + + for(DatapathId dpid : this.switches.keySet()) { + SwitchRepresentation representation = getSwitchRepresentation(dpid); + if(representation != null) { + representations.add(representation); + } + } + return representations; + } + + @Override + public void registerHandshakePlugin(IAppHandshakePluginFactory factory) { + Preconditions.checkState(floodlightProvider.getModuleLoaderState() == ModuleLoaderState.INIT, + "handshakeplugins can only be registered when the module loader is in state INIT!"); + handshakePlugins.add(factory); + } + + @Override + public List<IAppHandshakePluginFactory> getHandshakePlugins() { + return handshakePlugins; + } + + /* IFloodlightModule Implementation */ + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IOFSwitchService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); + m.put(IOFSwitchService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); + + l.add(IFloodlightProviderService.class); + l.add(IDebugEventService.class); + l.add(IDebugCounterService.class); + + return l; + } + + @Override + public void init(FloodlightModuleContext context) throws FloodlightModuleException { + // Module dependencies + floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); + debugEventService = context.getServiceImpl(IDebugEventService.class); + debugCounterService = context.getServiceImpl(IDebugCounterService.class); + + // Module variables + switchHandlers = new ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler>(); + switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>(); + floodlightProvider.getTimer(); + counters = new SwitchManagerCounters(debugCounterService); + driverRegistry = new NaiveSwitchDriverRegistry(this); + + this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>(); + + this.counters = new SwitchManagerCounters(debugCounterService); + + } + + @Override + public void startUp(FloodlightModuleContext context) throws FloodlightModuleException { + startUpBase(context); + bootstrapNetty(); + } + + /** + * Startup method that includes everything besides the netty boostrap. + * This has been isolated for testing. + * @param context floodlight module context + * @throws FloodlightModuleException + */ + public void startUpBase(FloodlightModuleContext context) throws FloodlightModuleException { + // Initial Role + role = floodlightProvider.getRole().getOFRole(); + + // IRoleListener + floodlightProvider.addHAListener(this); + + loadLogicalCategories(); + + registerDebugEvents(); + } + + /** + * Bootstraps netty, the server that handles all openflow connections + */ + public void bootstrapNetty() { + try { + final ServerBootstrap bootstrap = createServerBootStrap(); + + bootstrap.setOption("reuseAddr", true); + bootstrap.setOption("child.keepAlive", true); + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); + + ChannelPipelineFactory pfact = + new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService); + bootstrap.setPipelineFactory(pfact); + InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort()); + final ChannelGroup cg = new DefaultChannelGroup(); + cg.add(bootstrap.bind(sa)); + + log.info("Listening for switch connections on {}", sa); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Helper that bootstrapNetty. + * @return + */ + private ServerBootstrap createServerBootStrap() { + if (floodlightProvider.getWorkerThreads() == 0) { + return new ServerBootstrap( + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool())); + } else { + return new ServerBootstrap( + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads())); + } + } + + /** + * Performs startup related actions for logical OF message categories. + * Setting the categories list to immutable ensures that unsupported operation + * exceptions will be activated if modifications are attempted. + */ + public void loadLogicalCategories() { + logicalOFMessageCategories = ImmutableSet.copyOf(logicalOFMessageCategories); + numRequiredConnections = calcNumRequiredConnections(); + } + + /** + * Registers an event handler with the debug event service + * for switch events. + * @throws FloodlightModuleException + */ + private void registerDebugEvents() throws FloodlightModuleException { + if (debugEventService == null) { + debugEventService = new MockDebugEventService(); + } + evSwitch = debugEventService.buildEvent(SwitchEvent.class) + .setModuleName(this.counters.getPrefix()) + .setEventName("switch-event") + .setEventDescription("Switch connected, disconnected or port changed") + .setEventType(EventType.ALWAYS_LOG) + .setBufferCapacity(100) + .register(); + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type, + String name) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type, + String name) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void controllerNodeIPsChanged( + Map<String, String> curControllerNodeIPs, + Map<String, String> addedControllerNodeIPs, + Map<String, String> removedControllerNodeIPs) { + // TODO Auto-generated method stub + + } +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java b/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java deleted file mode 100644 index 82a3c67d658ddee3b20f702f2019117a044ccb4b..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java +++ /dev/null @@ -1,77 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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.core.internal; - -import java.util.concurrent.ThreadPoolExecutor; - -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.channel.ChannelPipelineFactory; -import org.jboss.netty.channel.Channels; -import org.jboss.netty.handler.execution.ExecutionHandler; -import org.jboss.netty.handler.timeout.IdleStateHandler; -import org.jboss.netty.handler.timeout.ReadTimeoutHandler; -import org.jboss.netty.util.ExternalResourceReleasable; -import org.jboss.netty.util.HashedWheelTimer; -import org.jboss.netty.util.Timer; - -/** - * Creates a ChannelPipeline for a server-side openflow channel - * @author readams - */ -public class OpenflowPipelineFactory - implements ChannelPipelineFactory, ExternalResourceReleasable { - - protected Controller controller; - protected ThreadPoolExecutor pipelineExecutor; - protected Timer timer; - protected IdleStateHandler idleHandler; - protected ReadTimeoutHandler readTimeoutHandler; - - public OpenflowPipelineFactory(Controller controller, - ThreadPoolExecutor pipelineExecutor) { - super(); - this.controller = controller; - this.pipelineExecutor = pipelineExecutor; - this.timer = new HashedWheelTimer(); - this.idleHandler = new IdleStateHandler(timer, 20, 25, 0); - this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30); - } - - @Override - public ChannelPipeline getPipeline() throws Exception { - OFChannelHandler handler = new OFChannelHandler(controller); - - ChannelPipeline pipeline = Channels.pipeline(); - pipeline.addLast("ofmessagedecoder", new OFMessageDecoder()); - pipeline.addLast("ofmessageencoder", new OFMessageEncoder()); - pipeline.addLast("idle", idleHandler); - pipeline.addLast("timeout", readTimeoutHandler); - pipeline.addLast("handshaketimeout", - new HandshakeTimeoutHandler(handler, timer, 15)); - if (pipelineExecutor != null) - pipeline.addLast("pipelineExecutor", - new ExecutionHandler(pipelineExecutor)); - pipeline.addLast("handler", handler); - return pipeline; - } - - @Override - public void releaseExternalResources() { - timer.stop(); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/internal/PluginResult.java b/src/main/java/net/floodlightcontroller/core/internal/PluginResult.java new file mode 100644 index 0000000000000000000000000000000000000000..e11a527de0a4df91c500bfd5e421fae6c9dd94c9 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/PluginResult.java @@ -0,0 +1,40 @@ +package net.floodlightcontroller.core.internal; + +import javax.annotation.Nonnull; + +import net.floodlightcontroller.core.internal.OFSwitchAppHandshakePlugin.PluginResultType; + +import com.google.common.base.Preconditions; + +/** + * Class that represents the result of an app handshake plugin. + * + */ +public class PluginResult { + + private final PluginResultType result; + private final String reason; + + public PluginResult(@Nonnull PluginResultType result) { + this.result = result; + this.reason = null; + } + + public PluginResult(@Nonnull PluginResultType result, String reason) { + Preconditions.checkNotNull(result, "result must not be null"); + + if(result != PluginResultType.QUARANTINE && reason != null) + throw new IllegalStateException("Reason can only be set for Quarantine PluginResult"); + + this.result = result; + this.reason = reason; + } + + public PluginResultType getResultType() { + return this.result; + } + + public String getReason() { + return this.reason; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/RoleManager.java b/src/main/java/net/floodlightcontroller/core/internal/RoleManager.java new file mode 100644 index 0000000000000000000000000000000000000000..f37da6707e7e24db99315f16ba02e935a898b00f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/RoleManager.java @@ -0,0 +1,258 @@ +package net.floodlightcontroller.core.internal; + +import java.util.Date; +import java.util.Map.Entry; + +import javax.annotation.Nonnull; + +import net.floodlightcontroller.core.HARole; +import net.floodlightcontroller.core.internal.Controller; +import net.floodlightcontroller.core.internal.RoleManagerCounters; +import net.floodlightcontroller.core.IHAListener; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.IOFSwitchBackend; +import net.floodlightcontroller.core.internal.IOFSwitchService; +import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler; +import net.floodlightcontroller.core.internal.Controller.IUpdate; + +import net.floodlightcontroller.core.internal.RoleManager; +import net.floodlightcontroller.core.internal.RoleManager.SwitchRoleUpdate; +import org.projectfloodlight.openflow.protocol.OFControllerRole; +import org.projectfloodlight.openflow.types.DatapathId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.floodlightcontroller.core.RoleInfo; + +/** + * A utility class to manage the <i>controller roles</i>. + * + * A utility class to manage the <i>controller roles</i> as opposed + * to the switch roles. The class manages the controllers current role, + * handles role change requests, and maintains the list of connected + * switch(-channel) so it can notify the switches of role changes. + * + * We need to ensure that every connected switch is always send the + * correct role. Therefore, switch add, sending of the intial role, and + * changing role need to use mutexes to ensure this. This has the ugly + * side-effect of requiring calls between controller and OFChannelHandler + * + * This class is fully thread safe. Its method can safely be called from + * any thread. + * + * @author gregor + * + */ +public class RoleManager { + private volatile RoleInfo currentRoleInfo; + private final Controller controller; + private final RoleManagerCounters counters; + private volatile boolean notifiedLeader; + + private static final Logger log = + LoggerFactory.getLogger(RoleManager.class); + + /** + * @param role initial role + * @param roleChangeDescription initial value of the change description + * @throws NullPointerException if role or roleChangeDescription is null + */ + public RoleManager(@Nonnull Controller controller, + @Nonnull HARole role, + @Nonnull String roleChangeDescription) { + Preconditions.checkNotNull(controller, "controller must not be null"); + Preconditions.checkNotNull(role, "role must not be null"); + Preconditions.checkNotNull(roleChangeDescription, "roleChangeDescription must not be null"); + + this.currentRoleInfo = new RoleInfo(role, + roleChangeDescription, + new Date()); + this.controller = controller; + this.counters = new RoleManagerCounters(controller.getDebugCounter()); + } + + /** + * Re-assert a role for the given channel handler. + * + * The caller specifies the role that should be reasserted. We only + * reassert the role if the controller's current role matches the + * reasserted role and there is no role request for the reasserted role + * pending. + * @param ofSwitchHandshakeHandler The OFChannelHandler on which we should reassert. + * @param role The role to reassert + */ + public synchronized void reassertRole(OFSwitchHandshakeHandler ofSwitchHandshakeHandler, HARole role) { + // check if the requested reassertion actually makes sense + if (this.getRole() != role) + return; + ofSwitchHandshakeHandler.sendRoleRequestIfNotPending(this.getRole().getOFRole()); + } + + /** + * Set the controller's new role and notify switches. + * + * This method updates the controllers current role and notifies all + * connected switches of the new role is different from the current + * role. We dampen calls to this method. See class description for + * details. + * + * @param role The new role. + * @param roleChangeDescription A textual description of why the role + * was changed. For information purposes only. + * @throws NullPointerException if role or roleChangeDescription is null + */ + public synchronized void setRole(@Nonnull HARole role, @Nonnull String roleChangeDescription) { + Preconditions.checkNotNull(role, "role must not be null"); + Preconditions.checkNotNull(roleChangeDescription, "roleChangeDescription must not be null"); + + if (role == getRole()) { + counters.setSameRole.increment(); + log.debug("Received role request for {} but controller is " + + "already {}. Ignoring it.", role, this.getRole()); + return; + } + + if (this.getRole() == HARole.STANDBY && role == HARole.ACTIVE) { + // At this point we are guaranteed that we will execute the code + // below exactly once during the lifetime of this process! And + // it will be a to MASTER transition + counters.setRoleMaster.increment(); + } + + log.info("Received role request for {} (reason: {})." + + " Initiating transition", role, roleChangeDescription); + + currentRoleInfo = + new RoleInfo(role, roleChangeDescription, new Date()); + + // NOTE: HARoleUpdate will terminate floodlight on transition to STANDBY + controller.addUpdateToQueue(new HARoleUpdate(role)); + controller.addUpdateToQueue(new SwitchRoleUpdate(role)); + + } + + @SuppressFBWarnings(value="UG_SYNC_SET_UNSYNC_GET", + justification = "setter is synchronized for mutual exclusion, " + + "currentRoleInfo is volatile, so no sync on getter needed") + public synchronized HARole getRole() { + return currentRoleInfo.getRole(); + } + + public synchronized OFControllerRole getOFControllerRole() { + return getRole().getOFRole(); + } + + /** + * Return the RoleInfo object describing the current role. + * + * Return the RoleInfo object describing the current role. The + * RoleInfo object is used by REST API users. + * @return the current RoleInfo object + */ + public RoleInfo getRoleInfo() { + return currentRoleInfo; + } + + private void attemptActiveTransition() { + if(!switchesHaveAnotherMaster()){ + // No valid cluster controller connections found, become ACTIVE! + setRole(HARole.ACTIVE, "Leader election assigned ACTIVE role"); + notifiedLeader = false; + } + } + + /** + * Iterates over all the switches and checks to see if they have controller + * connections that points towards another master controller. + * @return + */ + private boolean switchesHaveAnotherMaster() { + IOFSwitchService switchService = controller.getSwitchService(); + + for(Entry<DatapathId, IOFSwitch> switchMap : switchService.getAllSwitchMap().entrySet()){ + IOFSwitchBackend sw = (IOFSwitchBackend) switchMap.getValue(); + if(sw.hasAnotherMaster()){ + return true; + } + } + return false; + } + + public void notifyControllerConnectionUpdate() { + if(notifiedLeader && currentRoleInfo.getRole() != HARole.ACTIVE) { + attemptActiveTransition(); + } + } + + /** + * Update message indicating controller's role has changed. + * RoleManager, which enqueues these updates guarantees that we will + * only have a single transition from SLAVE to MASTER. + * + * When the role update from master to slave is complete, the HARoleUpdate + * will terminate floodlight. + */ + private class HARoleUpdate implements IUpdate { + private final HARole newRole; + public HARoleUpdate(HARole newRole) { + this.newRole = newRole; + } + + @Override + public void dispatch() { + if (log.isDebugEnabled()) { + log.debug("Dispatching HA Role update newRole = {}", + newRole); + } + for (IHAListener listener : controller.haListeners.getOrderedListeners()) { + if (log.isTraceEnabled()) { + log.trace("Calling HAListener {} with transitionTo{}", + listener.getName(), newRole); + } + switch(newRole) { + case ACTIVE: + listener.transitionToActive(); + break; + case STANDBY: + listener.transitionToStandby(); + break; + } + } + + controller.setNotifiedRole(newRole); + + if(newRole == HARole.STANDBY) { + String reason = String.format("Received role request to " + + "transition from ACTIVE to STANDBY (reason: %s)", + getRoleInfo().getRoleChangeDescription()); + //TODO @Ryan shutdownService.terminate(reason, 0); + } + } + } + + public class SwitchRoleUpdate implements IUpdate { + private final HARole role; + + public SwitchRoleUpdate(HARole role) { + this.role = role; + } + + @Override + public void dispatch() { + if (log.isDebugEnabled()) { + log.debug("Dispatching switch role update newRole = {}, switch role = {}", + this.role, this.role.getOFRole()); + } + + for (OFSwitchHandshakeHandler h: controller.getSwitchService().getSwitchHandshakeHandlers()) + h.sendRoleRequest(this.role.getOFRole()); + } + } + + public RoleManagerCounters getCounters() { + return this.counters; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java new file mode 100644 index 0000000000000000000000000000000000000000..04d948339ecedc0c487a57384481f155591eb328 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java @@ -0,0 +1,32 @@ +package net.floodlightcontroller.core.internal; + +import net.floodlightcontroller.debugcounter.IDebugCounter; +import net.floodlightcontroller.debugcounter.IDebugCounterService; +import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData; + + public class RoleManagerCounters { + + public final String prefix = RoleManager.class.getSimpleName(); + public final IDebugCounter setSameRole; + public final IDebugCounter setRoleMaster; + + public RoleManagerCounters(IDebugCounterService debugCounters) { + debugCounters.registerModule(prefix); + setSameRole = + debugCounters.registerCounter( + prefix, "set-same-role", + "Controller received a role request for the same " + + "role the controller already had", + MetaData.WARN); + + setRoleMaster = + debugCounters.registerCounter( + prefix, "set-role-master", + "Controller received a role request with role of " + + "MASTER. This counter can be at most 1."); + } + + public String getPrefix(){ + return this.prefix; + } + } \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..7a4f36b37cc54e5c9c5d7698ffc04b9ac7adba2d --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java @@ -0,0 +1,18 @@ +package net.floodlightcontroller.core.internal; + +import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; +import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType; +import org.projectfloodlight.openflow.types.DatapathId; + +public class SwitchEvent { + @EventColumn(name = "dpid", description = EventFieldType.DPID) + DatapathId dpid; + + @EventColumn(name = "reason", description = EventFieldType.STRING) + String reason; + + public SwitchEvent(DatapathId dpid, String reason) { + this.dpid = dpid; + this.reason = reason; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java new file mode 100644 index 0000000000000000000000000000000000000000..942809cd45d4a060c865a9355442830e713ae318 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java @@ -0,0 +1,208 @@ +package net.floodlightcontroller.core.internal; + +import net.floodlightcontroller.debugcounter.IDebugCounter; +import net.floodlightcontroller.debugcounter.IDebugCounterService; +import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData; + +public class SwitchManagerCounters { + + public final String prefix = OFSwitchManager.class.getSimpleName(); + public final IDebugCounter invalidPortsChanged; + public final IDebugCounter switchConnected; + public final IDebugCounter invalidSwitchActivatedWhileSlave; + public final IDebugCounter switchActivated; + public final IDebugCounter switchDeactivated; + public final IDebugCounter errorActivatedSwitchNotPresent; + public final IDebugCounter switchWithSameDpidActivated; + public final IDebugCounter switchDisconnected; + public final IDebugCounter switchPortChanged; + public final IDebugCounter switchOtherChange; + public final IDebugCounter switchDisconnectReadTimeout; + public final IDebugCounter switchDisconnectHandshakeTimeout; + public final IDebugCounter switchDisconnectIOError; + public final IDebugCounter switchDisconnectParseError; + public final IDebugCounter switchDisconnectSwitchStateException; + public final IDebugCounter rejectedExecutionException; + public final IDebugCounter switchDisconnectOtherException; + public final IDebugCounter unhandledMessage; + public final IDebugCounter packetInWhileSwitchIsSlave; + public final IDebugCounter roleNotResentBecauseRolePending; + public final IDebugCounter epermErrorWhileSwitchIsMaster; + public final IDebugCounter roleReplyTimeout; + public final IDebugCounter roleReplyReceived; + public final IDebugCounter roleReplyErrorUnsupported; + + public SwitchManagerCounters(IDebugCounterService debugCounters) { + debugCounters.registerModule(prefix); + invalidPortsChanged = + debugCounters.registerCounter( + prefix, "invalid-ports-changed", + "Received an unexpected ports changed " + + "notification while the controller was in " + + "SLAVE role.", + MetaData.WARN); + + invalidSwitchActivatedWhileSlave = + debugCounters.registerCounter( + prefix, "invalid-switch-activated-while-slave", + "Received an unexpected switchActivated " + + "notification while the controller was in " + + "SLAVE role.", + MetaData.WARN); + + switchActivated = + debugCounters.registerCounter( + prefix, "switch-activated", + "A switch connected to this controller is now " + + "in MASTER role"); + + switchDeactivated = + debugCounters.registerCounter( + prefix, "switch-activated", + "A switch connected to this controller is now " + + "in SLAVE role"); + + errorActivatedSwitchNotPresent = // err + debugCounters.registerCounter( + prefix, "error-same-switch-reactivated", + "A switch that was already in active state " + + "was activated again. This indicates a " + + "controller defect", + MetaData.ERROR); + + switchWithSameDpidActivated = // warn + debugCounters.registerCounter( + prefix, "switch-with-same-dpid-activated", + "A switch with the same DPID as another switch " + + "connected to the controller. This can be " + + "caused by multiple switches configured with " + + "the same DPID or by a switch reconnecting very " + + "quickly.", + MetaData.WARN); + + switchDisconnected = + debugCounters.registerCounter( + prefix, "switch-disconnected", + "FIXME: switch has disconnected"); + + switchPortChanged = + debugCounters.registerCounter( + prefix, "switch-port-changed", + "Number of times switch ports have changed"); + switchOtherChange = + debugCounters.registerCounter( + prefix, "switch-other-change", + "Number of times other information of a switch " + + "has changed."); + + switchDisconnectReadTimeout = + debugCounters.registerCounter( + prefix, "switch-disconnect-read-timeout", + "Number of times a switch was disconnected due " + + "due the switch failing to send OpenFlow " + + "messages or responding to OpenFlow ECHOs", + MetaData.ERROR); + switchDisconnectHandshakeTimeout = + debugCounters.registerCounter( + prefix, "switch-disconnect-handshake-timeout", + "Number of times a switch was disconnected " + + "because it failed to complete the handshake " + + "in time.", + MetaData.ERROR); + switchDisconnectIOError = + debugCounters.registerCounter( + prefix, "switch-disconnect-io-error", + "Number of times a switch was disconnected " + + "due to IO errors on the switch connection.", + MetaData.ERROR); + switchDisconnectParseError = + debugCounters.registerCounter( + prefix, "switch-disconnect-parse-error", + "Number of times a switch was disconnected " + + "because it sent an invalid packet that could " + + "not be parsed", + MetaData.ERROR); + + switchDisconnectSwitchStateException = + debugCounters.registerCounter( + prefix, "switch-disconnect-switch-state-exception", + "Number of times a switch was disconnected " + + "because it sent messages that were invalid " + + "given the switch connection's state.", + MetaData.ERROR); + rejectedExecutionException = + debugCounters.registerCounter( + prefix, "rejected-execution-exception", + "TODO", + MetaData.ERROR); + + switchDisconnectOtherException = + debugCounters.registerCounter( + prefix, "switch-disconnect-other-exception", + "Number of times a switch was disconnected " + + "due to an exceptional situation not covered " + + "by other counters", + MetaData.ERROR); + + switchConnected = + debugCounters.registerCounter( + prefix, "switch-connected", + "Number of times a new switch connection was " + + "established"); + + unhandledMessage = + debugCounters.registerCounter( + prefix, "unhandled-message", + "Number of times an OpenFlow message was " + + "received that the controller ignored because " + + "it was inapproriate given the switch " + + "connection's state.", + MetaData.WARN); + + packetInWhileSwitchIsSlave = + debugCounters.registerCounter( + prefix, "packet-in-while-switch-is-slave", + "Number of times a packet in was received " + + "from a switch that was in SLAVE role. " + + "Possibly inidicates inconsistent roles."); + epermErrorWhileSwitchIsMaster = + debugCounters.registerCounter( + prefix, "eperm-error-while-switch-is-master", + "Number of times a permission error was " + + "received while the switch was in MASTER role. " + + "Possibly inidicates inconsistent roles.", + MetaData.WARN); + + roleNotResentBecauseRolePending = + debugCounters.registerCounter( + prefix, "role-not-resent-because-role-pending", + "The controller tried to reestablish a role " + + "with a switch but did not do so because a " + + "previous role request was still pending"); + roleReplyTimeout = + debugCounters.registerCounter( + prefix, "role-reply-timeout", + "Number of times a role request message did not " + + "receive the expected reply from a switch", + MetaData.WARN); + + roleReplyReceived = // expected RoleReply received + debugCounters.registerCounter( + prefix, "role-reply-received", + "Number of times the controller received the " + + "expected role reply message from a switch"); + + roleReplyErrorUnsupported = + debugCounters.registerCounter( + prefix, "role-reply-error-unsupported", + "Number of times the controller received an " + + "error from a switch in response to a role " + + "request indicating that the switch does not " + + "support roles."); + } + + public String getPrefix(){ + return this.prefix; + } + +} diff --git a/src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java b/src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java deleted file mode 100644 index f56dfa996e90f9550a09fb3ae817ed4685431046..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java +++ /dev/null @@ -1,179 +0,0 @@ -package net.floodlightcontroller.core.module; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; - -/** - * Load an application from a configuration directory - * @author readams - */ -public class ApplicationLoader - implements IFloodlightModule, IApplicationService { - - /** - * Representation for the application configuration - * @author readams - */ - public static class Application { - private String name; - private String[] modules; - private Map<String,String> config; - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public String[] getModules() { - return modules; - } - public void setModules(String[] modules) { - this.modules = modules; - } - public Map<String, String> getConfig() { - return config; - } - public void setConfig(Map<String, String> config) { - this.config = config; - } - } - - - protected static Logger logger = - LoggerFactory.getLogger(ApplicationLoader.class); - protected static ObjectMapper mapper = new ObjectMapper(); - protected static ObjectReader reader = mapper.reader(Application.class); - - IModuleService moduleService; - - private static String APP_RESOURCE_PATH = "apps/"; - - /** - * Path containing application description files - */ - protected String applicationPath; - - /** - * Application to load - */ - protected String application; - - // ***************** - // IFloodlightModule - // ***************** - - @Override - public Collection<Class<? extends IFloodlightService>> - getModuleServices() { - Collection<Class<? extends IFloodlightService>> l = - new ArrayList<Class<? extends IFloodlightService>>(); - l.add(IApplicationService.class); - return l; - } - - @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> - getServiceImpls() { - - Map<Class<? extends IFloodlightService>, - IFloodlightService> m = - new HashMap<Class<? extends IFloodlightService>, - IFloodlightService>(); - // We are the class that implements the service - m.put(IApplicationService.class, this); - return m; - } - - @Override - public Collection<Class<? extends IFloodlightService>> - getModuleDependencies() { - return null; - } - - @Override - public void init(FloodlightModuleContext context) - throws FloodlightModuleException { - moduleService = context.getServiceImpl(IModuleService.class); - - Map<String,String> config = context.getConfigParams(this); - if (config.containsKey("appsd")) - applicationPath = config.get("appsd"); - if (config.containsKey("application")) - application = config.get("application"); - } - - @Override - public void startUp(FloodlightModuleContext context) - throws FloodlightModuleException { - if (application == null) { - throw new FloodlightModuleException("No application to load"); - } - - // attempt to load from application path - File appPath; - if (applicationPath != null && - (appPath = new File(applicationPath)).exists() && - appPath.isDirectory()) { - File[] files = appPath.listFiles(); - Arrays.sort(files); - for (File f : files) { - if (f.isFile() && f.getName().matches(".*\\.json$")); - try { - if (loadApplication(new FileInputStream(f), f.getPath())) - return; - } catch (FileNotFoundException e) { - throw new FloodlightModuleException(e); - } - } - } - - // attempt to load from classpath. Note here that the file needs - // to be named after the application to be successful - try { - String r = APP_RESOURCE_PATH + application + ".json"; - InputStream is = getClass().getClassLoader().getResourceAsStream(r); - loadApplication(is, "resource: " + r); - } catch (Exception e) { - throw new FloodlightModuleException(e); - } - - } - - private boolean loadApplication(InputStream is, String path) - throws FloodlightModuleException { - Application a; - try { - a = reader.readValue(is); - } catch (Exception e) { - throw new FloodlightModuleException("Could not read application " + - path, e); - } - if (application.equals(a.getName())) { - Properties p = new Properties(); - if (a.getConfig() != null) - p.putAll(a.getConfig()); - if (a.getModules() != null) { - logger.info("Loading application {}", a.getName()); - moduleService.loadModulesFromList(Arrays.asList(a.getModules()), - p); - return true; - } - } - return false; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..e20d1e06f74d572590ca63d4660c799b4278a2fd --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java @@ -0,0 +1,10 @@ +package net.floodlightcontroller.core.module; + +public class FloodlightModuleConfigFileNotFoundException extends + FloodlightModuleException { + private static final long serialVersionUID = 1L; + + public FloodlightModuleConfigFileNotFoundException(String fileName) { + super("No such file or directory: " + fileName); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java deleted file mode 100644 index 27c1f968ac0534ecf1bfcd293ce471669016719e..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * The service registry for an IFloodlightProvider. - * @author alexreimers - */ -public class FloodlightModuleContext implements IFloodlightModuleContext { - protected Map<Class<? extends IFloodlightService>, IFloodlightService> serviceMap; - protected Map<Class<? extends IFloodlightModule>, Map<String, String>> configParams; - protected Collection<IFloodlightModule> moduleSet; - - /** - * Creates the ModuleContext for use with this IFloodlightProvider. - * This will be used as a module registry for all IFloodlightModule(s). - */ - public FloodlightModuleContext() { - serviceMap = - new HashMap<Class<? extends IFloodlightService>, - IFloodlightService>(); - configParams = - new HashMap<Class<? extends IFloodlightModule>, - Map<String, String>>(); - } - - /** - * Adds a IFloodlightModule for this Context. - * @param clazz the service class - * @param service The IFloodlightService to add to the registry - */ - public void addService(Class<? extends IFloodlightService> clazz, - IFloodlightService service) { - serviceMap.put(clazz, service); - } - - @SuppressWarnings("unchecked") - @Override - public <T extends IFloodlightService> T getServiceImpl(Class<T> service) { - IFloodlightService s = serviceMap.get(service); - return (T)s; - } - - @Override - public Collection<Class<? extends IFloodlightService>> getAllServices() { - return serviceMap.keySet(); - } - - @Override - public Collection<IFloodlightModule> getAllModules() { - return moduleSet; - } - - public void addModules(Collection<IFloodlightModule> modSet) { - if (this.moduleSet == null) - this.moduleSet = new ArrayList<IFloodlightModule>(); - this.moduleSet.addAll(modSet); - } - - @Override - public Map<String, String> getConfigParams(IFloodlightModule module) { - Class<? extends IFloodlightModule> clazz = module.getClass(); - return getConfigParams(clazz); - } - - @Override - public Map<String, String> getConfigParams(Class<? extends IFloodlightModule> clazz) { - Map<String, String> retMap = configParams.get(clazz); - if (retMap == null) { - // Return an empty map if none exists so the module does not - // need to null check the map - retMap = new HashMap<String, String>(); - configParams.put(clazz, retMap); - } - - // also add any configuration parameters for superclasses, but - // only if more specific configuration does not override it - for (Class<? extends IFloodlightModule> c : configParams.keySet()) { - if (c.isAssignableFrom(clazz)) { - for (Map.Entry<String, String> ent : configParams.get(c).entrySet()) { - if (!retMap.containsKey(ent.getKey())) { - retMap.put(ent.getKey(), ent.getValue()); - } - } - } - } - - return retMap; - } - - /** - * Adds a configuration parameter for a module - * @param mod The fully qualified module name to add the parameter to - * @param key The configuration parameter key - * @param value The configuration parameter value - */ - public void addConfigParam(IFloodlightModule mod, String key, String value) { - Map<String, String> moduleParams = configParams.get(mod.getClass()); - if (moduleParams == null) { - moduleParams = new HashMap<String, String>(); - configParams.put(mod.getClass(), moduleParams); - } - moduleParams.put(key, value); - } - } diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java deleted file mode 100644 index 5cddd37fccb8564ae7e31b6f2418a2339ce354c7..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -public class FloodlightModuleException extends Exception { - private static final long serialVersionUID = 1L; - - public FloodlightModuleException(String error) { - super(error); - } - - public FloodlightModuleException() { - super(); - } - - public FloodlightModuleException(String message, Throwable cause) { - super(message, cause); - } - - public FloodlightModuleException(Throwable cause) { - super(cause); - } -} diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java deleted file mode 100644 index 32e4fc031e26eafee38bd282e0a1b21e0b73ebfb..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java +++ /dev/null @@ -1,501 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.Queue; -import java.util.ServiceConfigurationError; -import java.util.ServiceLoader; -import java.util.Set; - -import net.floodlightcontroller.core.annotations.LogMessageDoc; -import net.floodlightcontroller.core.annotations.LogMessageDocs; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Finds all Floodlight modules in the class path and loads/starts them. - * @author alexreimers - * - */ -public class FloodlightModuleLoader implements IModuleService { - protected static Logger logger = - LoggerFactory.getLogger(FloodlightModuleLoader.class); - - protected static Map<Class<? extends IFloodlightService>, - Collection<IFloodlightModule>> serviceMap; - protected static Map<IFloodlightModule, - Collection<Class<? extends - IFloodlightService>>> moduleServiceMap; - protected static Map<String, IFloodlightModule> moduleNameMap; - protected static Object lock = new Object(); - - protected static Set<String> initedSet = new HashSet<String>(); - protected static Set<String> startedSet = new HashSet<String>();; - - protected FloodlightModuleContext floodlightModuleContext; - - public static final String COMPILED_CONF_FILE = - "floodlightdefault.properties"; - public static final String FLOODLIGHT_MODULES_KEY = - "floodlight.modules"; - public static final String FLOODLIGHT_CONFD = - "floodlight.confd"; - - public FloodlightModuleLoader() { - floodlightModuleContext = new FloodlightModuleContext(); - floodlightModuleContext.addService(IModuleService.class, this); - } - - /** - * Finds all IFloodlightModule(s) in the classpath. It creates 3 Maps. - * serviceMap -> Maps a service to a module - * moduleServiceMap -> Maps a module to all the services it provides - * moduleNameMap -> Maps the string name to the module - * @throws FloodlightModuleException If two modules are specified in the configuration - * that provide the same service. - */ - protected static void findAllModules(Collection<String> mList) throws FloodlightModuleException { - synchronized (lock) { - if (serviceMap != null) return; - serviceMap = - new HashMap<Class<? extends IFloodlightService>, - Collection<IFloodlightModule>>(); - moduleServiceMap = - new HashMap<IFloodlightModule, - Collection<Class<? extends - IFloodlightService>>>(); - moduleNameMap = new HashMap<String, IFloodlightModule>(); - - // Get all the current modules in the classpath - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - ServiceLoader<IFloodlightModule> moduleLoader - = ServiceLoader.load(IFloodlightModule.class, cl); - // Iterate for each module, iterate through and add it's services - Iterator<IFloodlightModule> moduleIter = moduleLoader.iterator(); - while (moduleIter.hasNext()) { - IFloodlightModule m = null; - try { - m = moduleIter.next(); - } catch (ServiceConfigurationError sce) { - logger.error("Could not find module: {}", sce.getMessage()); - continue; - } - //} - //for (IFloodlightModule m : moduleLoader) { - if (logger.isDebugEnabled()) { - logger.debug("Found module " + m.getClass().getName()); - } - - // Set up moduleNameMap - moduleNameMap.put(m.getClass().getCanonicalName(), m); - - // Set up serviceMap - Collection<Class<? extends IFloodlightService>> servs = - m.getModuleServices(); - if (servs != null) { - moduleServiceMap.put(m, servs); - for (Class<? extends IFloodlightService> s : servs) { - Collection<IFloodlightModule> mods = - serviceMap.get(s); - if (mods == null) { - mods = new ArrayList<IFloodlightModule>(); - serviceMap.put(s, mods); - } - mods.add(m); - // Make sure they haven't specified duplicate modules in the config - int dupInConf = 0; - for (IFloodlightModule cMod : mods) { - if (mList.contains(cMod.getClass().getCanonicalName())) - dupInConf += 1; - } - - if (dupInConf > 1) { - String duplicateMods = ""; - for (IFloodlightModule mod : mods) { - duplicateMods += mod.getClass().getCanonicalName() + ", "; - } - throw new FloodlightModuleException("ERROR! The configuraiton" + - " file specifies more than one module that provides the service " + - s.getCanonicalName() +". Please specify only ONE of the " + - "following modules in the config file: " + duplicateMods); - } - } - } - } - } - } - - /** - * Loads the modules from a specified configuration file. - * @param fName The configuration file path - * @return An IFloodlightModuleContext with all the modules to be started - * @throws FloodlightModuleException - */ - @LogMessageDocs({ - @LogMessageDoc(level="INFO", - message="Loading modules from file {file name}", - explanation="The controller is initializing its module " + - "configuration from the specified properties file"), - @LogMessageDoc(level="INFO", - message="Loading default modules", - explanation="The controller is initializing its module " + - "configuration to the default configuration"), - @LogMessageDoc(level="ERROR", - message="Could not load module configuration file", - explanation="The controller failed to read the " + - "module configuration file", - recommendation="Verify that the module configuration is " + - "present. " + LogMessageDoc.CHECK_CONTROLLER), - @LogMessageDoc(level="ERROR", - message="Could not load default modules", - explanation="The controller failed to read the default " + - "module configuration", - recommendation=LogMessageDoc.CHECK_CONTROLLER) - }) - public IFloodlightModuleContext loadModulesFromConfig(String fName) - throws FloodlightModuleException { - Properties prop = new Properties(); - Collection<String> configMods; - - File f = new File(fName); - if (f.isFile()) { - logger.info("Loading modules from file {}", f.getPath()); - configMods = loadProperties(null, f, prop); - } else { - logger.info("Loading default modules"); - InputStream is = this.getClass().getClassLoader(). - getResourceAsStream(COMPILED_CONF_FILE); - configMods = loadProperties(is, null, prop); - } - - return loadModulesFromList(configMods, prop); - } - - private Collection<String> loadProperties(InputStream is, - File confFile, - Properties prop) { - try { - Properties fprop = new Properties(); - if (is != null) { - fprop.load(is); - } else { - fprop.load(new FileInputStream(confFile)); - } - prop.putAll(fprop); - } catch (Exception e) { - logger.error("Could not load module configuration file", e); - System.exit(1); - } - - Collection<String> configMods = new ArrayList<String>(); - String moduleList = prop.getProperty(FLOODLIGHT_MODULES_KEY); - if (moduleList != null) { - moduleList = moduleList.replaceAll("\\s", ""); - configMods.addAll(Arrays.asList(moduleList.split(","))); - prop.remove(FLOODLIGHT_MODULES_KEY); - } - - String confdStr = prop.getProperty(FLOODLIGHT_CONFD); - prop.remove(FLOODLIGHT_CONFD); - if (confdStr != null) { - File confd = new File(confdStr); - if (confd.exists() && confd.isDirectory()) { - File[] files = confd.listFiles(); - Arrays.sort(files); - for (File f : files) { - if (f.isFile() && - f.getName().matches(".*\\.properties$")) - configMods.addAll(loadProperties(null, f, prop)); - } - } - } - - return configMods; - } - - /** - * Loads modules (and their dependencies) specified in the list - * @param mList The array of fully qualified module names - * @param ignoreList The list of Floodlight services NOT to - * load modules for. Used for unit testing. - * @return The ModuleContext containing all the loaded modules - * @throws FloodlightModuleException - */ - protected IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop, - Collection<IFloodlightService> ignoreList) throws FloodlightModuleException { - logger.debug("Starting module loader"); - if (logger.isDebugEnabled() && ignoreList != null) - logger.debug("Not loading module services " + ignoreList.toString()); - - findAllModules(configMods); - - Collection<IFloodlightModule> moduleSet = new ArrayList<IFloodlightModule>(); - Map<Class<? extends IFloodlightService>, IFloodlightModule> moduleMap = - new HashMap<Class<? extends IFloodlightService>, - IFloodlightModule>(); - - Queue<String> moduleQ = new LinkedList<String>(); - // Add the explicitly configured modules to the q - moduleQ.addAll(configMods); - Set<String> modsVisited = new HashSet<String>(); - - while (!moduleQ.isEmpty()) { - String moduleName = moduleQ.remove(); - if (modsVisited.contains(moduleName)) - continue; - modsVisited.add(moduleName); - IFloodlightModule module = moduleNameMap.get(moduleName); - if (module == null) { - throw new FloodlightModuleException("Module " + - moduleName + " not found"); - } - // If the module provides a service that is in the - // services ignorelist don't load it. - if ((ignoreList != null) && (module.getModuleServices() != null)) { - for (IFloodlightService ifs : ignoreList) { - for (Class<?> intsIgnore : ifs.getClass().getInterfaces()) { - //System.out.println(intsIgnore.getName()); - // Check that the interface extends IFloodlightService - //if (intsIgnore.isAssignableFrom(IFloodlightService.class)) { - //System.out.println(module.getClass().getName()); - if (intsIgnore.isAssignableFrom(module.getClass())) { - // We now ignore loading this module. - logger.debug("Not loading module " + - module.getClass().getCanonicalName() + - " because interface " + - intsIgnore.getCanonicalName() + - " is in the ignore list."); - - continue; - } - //} - } - } - } - - // Add the module to be loaded - addModule(moduleMap, moduleSet, module); - // Add it's dep's to the queue - Collection<Class<? extends IFloodlightService>> deps = - module.getModuleDependencies(); - if (deps != null) { - for (Class<? extends IFloodlightService> c : deps) { - IFloodlightModule m = moduleMap.get(c); - if (m == null) { - Collection<IFloodlightModule> mods = serviceMap.get(c); - // Make sure only one module is loaded - if ((mods == null) || (mods.size() == 0)) { - throw new FloodlightModuleException("ERROR! Could not " + - "find an IFloodlightModule that provides service " + - c.toString()); - } else if (mods.size() == 1) { - IFloodlightModule mod = mods.iterator().next(); - if (!modsVisited.contains(mod.getClass().getCanonicalName())) - moduleQ.add(mod.getClass().getCanonicalName()); - } else { - boolean found = false; - for (IFloodlightModule moduleDep : mods) { - if (configMods.contains(moduleDep.getClass().getCanonicalName())) { - // Module will be loaded, we can continue - found = true; - break; - } - } - if (!found) { - String duplicateMods = ""; - for (IFloodlightModule mod : mods) { - duplicateMods += mod.getClass().getCanonicalName() + ", "; - } - throw new FloodlightModuleException("ERROR! Found more " + - "than one (" + mods.size() + ") IFloodlightModules that provides " + - "service " + c.toString() + - ". This service is required for " + moduleName + - ". Please specify one of the following modules in the config: " + - duplicateMods); - } - } - } - } - } - } - - floodlightModuleContext.addModules(moduleSet); - parseConfigParameters(prop); - initModules(moduleSet); - startupModules(moduleSet); - - return floodlightModuleContext; - } - - @Override - public IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop) - throws FloodlightModuleException { - return loadModulesFromList(configMods, prop, null); - } - - /** - * Add a module to the set of modules to load and register its services - * @param moduleMap the module map - * @param moduleSet the module set - * @param module the module to add - */ - protected void addModule(Map<Class<? extends IFloodlightService>, - IFloodlightModule> moduleMap, - Collection<IFloodlightModule> moduleSet, - IFloodlightModule module) { - if (!moduleSet.contains(module)) { - Collection<Class<? extends IFloodlightService>> servs = - moduleServiceMap.get(module); - if (servs != null) { - for (Class<? extends IFloodlightService> c : servs) - moduleMap.put(c, module); - } - moduleSet.add(module); - } - } - - /** - * Allocate service implementations and then init all the modules - * @param moduleSet The set of modules to call their init function on - * @throws FloodlightModuleException If a module can not properly be loaded - */ - protected void initModules(Collection<IFloodlightModule> moduleSet) - throws FloodlightModuleException { - for (IFloodlightModule module : moduleSet) { - if (initedSet.contains(module.getClass().getCanonicalName())) - continue; - - // Get the module's service instance(s) - Map<Class<? extends IFloodlightService>, - IFloodlightService> simpls = module.getServiceImpls(); - - // add its services to the context - if (simpls != null) { - for (Entry<Class<? extends IFloodlightService>, - IFloodlightService> s : simpls.entrySet()) { - if (logger.isDebugEnabled()) { - logger.debug("Setting " + s.getValue() + - " as provider for " + - s.getKey().getCanonicalName()); - } - if (floodlightModuleContext.getServiceImpl(s.getKey()) == null) { - floodlightModuleContext.addService(s.getKey(), - s.getValue()); - } else { - throw new FloodlightModuleException("Cannot set " - + s.getValue() - + " as the provider for " - + s.getKey().getCanonicalName() - + " because " - + floodlightModuleContext.getServiceImpl(s.getKey()) - + " already provides it"); - } - } - } - } - - for (IFloodlightModule module : moduleSet) { - if (initedSet.contains(module.getClass().getCanonicalName())) - continue; - initedSet.add(module.getClass().getCanonicalName()); - - // init the module - if (logger.isDebugEnabled()) { - logger.debug("Initializing " + - module.getClass().getCanonicalName()); - } - module.init(floodlightModuleContext); - } - } - - /** - * Call each loaded module's startup method - * @param moduleSet the module set to start up - * @throws FloodlightModuleException - */ - protected void startupModules(Collection<IFloodlightModule> moduleSet) - throws FloodlightModuleException { - for (IFloodlightModule m : moduleSet) { - if (startedSet.contains(m.getClass().getCanonicalName())) - continue; - startedSet.add(m.getClass().getCanonicalName()); - - if (logger.isDebugEnabled()) { - logger.debug("Starting " + m.getClass().getCanonicalName()); - } - m.startUp(floodlightModuleContext); - } - } - - /** - * Parses configuration parameters for each module - * @param prop The properties file to use - */ - @LogMessageDoc(level="WARN", - message="Module {module} not found or loaded. " + - "Not adding configuration option {key} = {value}", - explanation="Ignoring a configuration parameter for a " + - "module that is not loaded.") - protected void parseConfigParameters(Properties prop) { - if (prop == null) return; - - Enumeration<?> e = prop.propertyNames(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - // Ignore module list key - if (key.equals(FLOODLIGHT_MODULES_KEY)) { - continue; - } - - String configValue = null; - int lastPeriod = key.lastIndexOf("."); - String moduleName = key.substring(0, lastPeriod); - String configKey = key.substring(lastPeriod + 1); - // Check to see if it's overridden on the command line - String systemKey = System.getProperty(key); - if (systemKey != null) { - configValue = systemKey; - } else { - configValue = prop.getProperty(key); - } - - IFloodlightModule mod = moduleNameMap.get(moduleName); - if (mod == null) { - logger.warn("Module {} not found or loaded. " + - "Not adding configuration option {} = {}", - new Object[]{moduleName, configKey, configValue}); - } else { - floodlightModuleContext.addConfigParam(mod, configKey, configValue); - } - } - } -} diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java new file mode 100644 index 0000000000000000000000000000000000000000..d2e561fbf435049f16fe80c885941c3e50deae40 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java @@ -0,0 +1,58 @@ +/** + * Copyright 2013, Big Switch Networks, Inc. + * + * 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.core.module; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Set a module priority value so if there are multiple modules that provide + * a given service, and there is a unique module with maximum priority, + * we will use that module in preference to lower-priority modules rather + * than requiring users to manually specify a module to load. This makes it + * possible to define a default provider that uses the DEFAULT_PROVIDER priority + * while the normal modules omit the annotation or specify NORMAL priority. + * @author readams + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface FloodlightModulePriority { + public enum Priority { + MINIMUM(0), + TEST(10), + EXTRA_LOW(20), + LOW(30), + NORMAL(40), + DEFAULT_PROVIDER(50), + HIGH(60), + EXTRA_HIGH(70); + + private final int value; + + private Priority(int value) { + this.value = value; + } + + public int value() { + return value; + } + } + + public Priority value() default Priority.NORMAL; +} diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java new file mode 100644 index 0000000000000000000000000000000000000000..c5d24b72313ee1234ca5beea1a7c9cafef229f38 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java @@ -0,0 +1,5 @@ +package net.floodlightcontroller.core.module; + +public @interface FloodlightServices { + +} diff --git a/src/main/java/net/floodlightcontroller/core/module/IApplicationService.java b/src/main/java/net/floodlightcontroller/core/module/IApplicationService.java deleted file mode 100644 index 60a916930a06185f5a11199bd1cd839d9ebf8f2b..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/IApplicationService.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.floodlightcontroller.core.module; - -public interface IApplicationService extends IFloodlightService { - -} diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java deleted file mode 100644 index 982e4be26a7e073dd700599a96a4393697088ed3..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -import java.util.Collection; -import java.util.Map; - - -/** - * Defines an interface for loadable Floodlight modules. - * - * At a high level, these functions are called in the following order: - * <ol> - * <li> getServices() : what services does this module provide - * <li> getDependencies() : list the dependencies - * <li> init() : internal initializations (don't touch other modules) - * <li> startUp() : external initializations (<em>do</em> touch other modules) - * </ol> - * - * @author alexreimers - */ -public interface IFloodlightModule { - - /** - * Return the list of interfaces that this module implements. - * All interfaces must inherit IFloodlightService - * @return - */ - - public Collection<Class<? extends IFloodlightService>> getModuleServices(); - - /** - * Instantiate (as needed) and return objects that implement each - * of the services exported by this module. The map returned maps - * the implemented service to the object. The object could be the - * same object or different objects for different exported services. - * @return The map from service interface class to service implementation - */ - public Map<Class<? extends IFloodlightService>, - IFloodlightService> getServiceImpls(); - - /** - * Get a list of Modules that this module depends on. The module system - * will ensure that each these dependencies is resolved before the - * subsequent calls to init(). - * @return The Collection of IFloodlightServices that this module depends - * on. - */ - - public Collection<Class<? extends IFloodlightService>> getModuleDependencies(); - - /** - * This is a hook for each module to do its <em>internal</em> initialization, - * e.g., call setService(context.getService("Service")) - * - * All module dependencies are resolved when this is called, but not every module - * is initialized. - * - * @param context - * @throws FloodlightModuleException - */ - - void init(FloodlightModuleContext context) throws FloodlightModuleException; - - /** - * This is a hook for each module to do its <em>external</em> initializations, - * e.g., register for callbacks or query for state in other modules - * - * It is expected that this function will not block and that modules that want - * non-event driven CPU will spawn their own threads. - * - * @param context - * @throws FloodlightModuleException - */ - - void startUp(FloodlightModuleContext context) - throws FloodlightModuleException; -} diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java deleted file mode 100644 index 46dea092c2eaa20b180b2176ddd3babbb2d24b26..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -import java.util.Collection; -import java.util.Map; - - -public interface IFloodlightModuleContext { - /** - * Retrieves a casted version of a module from the registry. - * @param name The IFloodlightService object type - * @return The IFloodlightService - * @throws FloodlightModuleException If the module was not found - * or a ClassCastException was encountered. - */ - public <T extends IFloodlightService> T getServiceImpl(Class<T> service); - - /** - * Returns all loaded services - * @return A collection of service classes that have been loaded - */ - public Collection<Class<? extends IFloodlightService>> getAllServices(); - - /** - * Returns all loaded modules - * @return All Floodlight modules that are going to be loaded - */ - public Collection<IFloodlightModule> getAllModules(); - - /** - * Gets module specific configuration parameters. - * @param module The module to get the configuration parameters for - * @return A key, value map of the configuration options - */ - public Map<String, String> getConfigParams(IFloodlightModule module); - - /** - * Gets module specific configuration parameters. - * @param clazz The class of the module to get configuration parameters for - * @return A key, value map of the configuration options - */ - public Map<String, String> getConfigParams(Class<? extends - IFloodlightModule> clazz); -} diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java deleted file mode 100644 index 4a5f4ca653a3fb5e09b651e87d3f302d8506ce14..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -/** - * This is the base interface for any IFloodlightModule package that provides - * a service. - * @author alexreimers - * - */ -public abstract interface IFloodlightService { - // This space is intentionally left blank....don't touch it -} diff --git a/src/main/java/net/floodlightcontroller/core/module/IModuleService.java b/src/main/java/net/floodlightcontroller/core/module/IModuleService.java deleted file mode 100644 index 440ad2de6240709ef9e8a068e4b557f6b1444d82..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/IModuleService.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.floodlightcontroller.core.module; - -import java.util.Collection; -import java.util.Properties; - -public interface IModuleService extends IFloodlightService { - /** - * Loads modules (and their dependencies) specified in the list. - * @param configMods The collection of fully qualified module names to load. - * @param prop The list of properties that are configuration options. - * @return The ModuleContext containing all the loaded modules. - * @throws FloodlightModuleException - */ - public IFloodlightModuleContext - loadModulesFromList(Collection<String> configMods, - Properties prop) throws FloodlightModuleException; - -} diff --git a/src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java b/src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java deleted file mode 100644 index b4406117effee39794485dcedac4885fbea0a3ad..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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.core.module; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - - -import org.restlet.resource.Get; -import org.restlet.resource.ServerResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Returns list of modules loaded by Floodlight. - * @author Rob Sherwood - */ -public class ModuleLoaderResource extends ServerResource { - protected static Logger log = - LoggerFactory.getLogger(ModuleLoaderResource.class); - - /** - * Retrieves information about loaded modules. - * @return Information about loaded modules. - */ - @Get("json") - public Map<String, Object> retrieve() { - return retrieveInternal(false); - } - - /** - * Retrieves all modules and their dependencies available - * to Floodlight. - * @param loadedOnly Whether to return all modules available or only the ones loaded. - * @return Information about modules available or loaded. - */ - public Map<String, Object> retrieveInternal(boolean loadedOnly) { - Map<String, Object> model = new HashMap<String, Object>(); - - Set<String> loadedModules = new HashSet<String>(); - for (Object val : getContext().getAttributes().values()) { - if ((val instanceof IFloodlightModule) || (val instanceof IFloodlightService)) { - String serviceImpl = val.getClass().getCanonicalName(); - loadedModules.add(serviceImpl); - // log.debug("Tracking serviceImpl " + serviceImpl); - } - } - - for (String moduleName : - FloodlightModuleLoader.moduleNameMap.keySet() ) { - Map<String,Object> moduleInfo = new HashMap<String, Object>(); - - IFloodlightModule module = - FloodlightModuleLoader.moduleNameMap.get( - moduleName); - - Collection<Class<? extends IFloodlightService>> deps = - module.getModuleDependencies(); - if ( deps == null) - deps = new HashSet<Class<? extends IFloodlightService>>(); - Map<String,Object> depsMap = new HashMap<String, Object> (); - for (Class<? extends IFloodlightService> service : deps) { - Object serviceImpl = getContext().getAttributes().get(service.getCanonicalName()); - if (serviceImpl != null) - depsMap.put(service.getCanonicalName(), serviceImpl.getClass().getCanonicalName()); - else - depsMap.put(service.getCanonicalName(), "<unresolved>"); - - } - moduleInfo.put("depends", depsMap); - - Collection<Class<? extends IFloodlightService>> provides = - module.getModuleServices(); - if ( provides == null) - provides = new HashSet<Class<? extends IFloodlightService>>(); - Map<String,Object> providesMap = new HashMap<String,Object>(); - for (Class<? extends IFloodlightService> service : provides) { - providesMap.put(service.getCanonicalName(), module.getServiceImpls().get(service).getClass().getCanonicalName()); - } - moduleInfo.put("provides", providesMap); - - moduleInfo.put("loaded", false); // not loaded, by default - - // check if this module is loaded directly - if (loadedModules.contains(module.getClass().getCanonicalName())) { - moduleInfo.put("loaded", true); - } else { - // if not, then maybe one of the services it exports is loaded - for (Class<? extends IFloodlightService> service : provides) { - String modString = module.getServiceImpls().get(service).getClass().getCanonicalName(); - if (loadedModules.contains(modString)) - moduleInfo.put("loaded", true); - /* else - log.debug("ServiceImpl not loaded " + modString); */ - } - } - - if ((Boolean)moduleInfo.get("loaded")|| !loadedOnly ) - model.put(moduleName, moduleInfo); - } - return model; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/module/Run.java b/src/main/java/net/floodlightcontroller/core/module/Run.java new file mode 100644 index 0000000000000000000000000000000000000000..4bf8a2ed41d270282b5dbda582a8ac7c32ec448f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/module/Run.java @@ -0,0 +1,20 @@ +package net.floodlightcontroller.core.module; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicate the run() method of a floodlight module + * @author readams + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Run { + /** declares this run method as the application main method. Will be called last and is not expected to + * return. It is a configuration error to have more than one module declaring a main method. + * @return + */ + boolean mainLoop() default false; +} diff --git a/src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java b/src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java new file mode 100644 index 0000000000000000000000000000000000000000..3d0fe680e544ffa5a7701ad42f0037fe8de9037c --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java @@ -0,0 +1,39 @@ +package net.floodlightcontroller.core.rest; + +import org.projectfloodlight.openflow.protocol.OFAggregateStatsReply; +import org.projectfloodlight.openflow.types.U64; + +public class AggregateStatistics { + + private final U64 packetCount; + private final U64 byteCount; + private final long flowCount; + + private AggregateStatistics(U64 packetCount, U64 byteCount, long flowCount) { + this.packetCount = packetCount; + this.byteCount = byteCount; + this.flowCount = flowCount; + } + + public static AggregateStatistics of(U64 packetCount, U64 byteCount, + long flowCount) { + return new AggregateStatistics(packetCount, byteCount, flowCount); + } + + public static AggregateStatistics of(OFAggregateStatsReply statsReply) { + return new AggregateStatistics(statsReply.getPacketCount(), + statsReply.getByteCount(), statsReply.getFlowCount()); + } + + public U64 getPacketCount() { + return packetCount; + } + + public U64 getByteCount() { + return byteCount; + } + + public long getFlowCount() { + return flowCount; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java b/src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java new file mode 100644 index 0000000000000000000000000000000000000000..03a46f462b68300c61639052b03a7931bfcc4861 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java @@ -0,0 +1,116 @@ +package net.floodlightcontroller.core.rest; + +import java.net.SocketAddress; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nonnull; + +import net.floodlightcontroller.core.IOFConnection; +import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler; +import org.projectfloodlight.openflow.protocol.OFCapabilities; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.types.DatapathId; + +import com.google.common.base.Preconditions; + +/** + * REST representation of an OF Switch. Stitches together data from different + * areas of the platform to provide a complete, centralized representation. + * @author Jason Parraga <Jason.Parraga@bigswitch.com> + * + */ +public class SwitchRepresentation { + + private final long buffers; + private final Set<OFCapabilities> capabilities; + private final Short tables; + private final SocketAddress inetAddress; + private final Collection<OFPortDesc> sortedPorts; + private final boolean isConnected; + private final Date connectedSince; + private final DatapathId dpid; + private final Map<Object, Object> attributes; + private final boolean isActive; + + private final Collection<IOFConnection> connections; + private final String handshakeState; + private final String quarantineReason; + + public SwitchRepresentation(@Nonnull IOFSwitch sw, @Nonnull OFSwitchHandshakeHandler handshakeHandler) { + Preconditions.checkNotNull(sw, "switch must not be null"); + Preconditions.checkNotNull(handshakeHandler, "handshakeHandler must not be null"); + + // IOFSwitch + this.buffers = sw.getBuffers(); + this.capabilities = sw.getCapabilities(); + this.tables = sw.getTables(); + this.inetAddress = sw.getInetAddress(); + this.sortedPorts = sw.getSortedPorts(); + this.isConnected = sw.isConnected(); + this.connectedSince = sw.getConnectedSince(); + this.dpid = sw.getId(); + this.attributes = sw.getAttributes(); + this.isActive = sw.isActive(); + + // OFSwitchHandshakeHandler + this.connections = handshakeHandler.getConnections(); + this.handshakeState = handshakeHandler.getState(); + this.quarantineReason = handshakeHandler.getQuarantineReason(); + } + + public long getBuffers() { + return this.buffers; + } + + public Short getTables() { + return this.tables; + } + + public Set<OFCapabilities> getCapabilities() { + return this.capabilities; + } + + public SocketAddress getInetAddress() { + return this.inetAddress; + } + + public Collection<OFPortDesc> getSortedPorts() { + return this.sortedPorts; + } + + public boolean isConnected() { + return this.isConnected; + } + + public Date getConnectedSince() { + return this.connectedSince; + } + + public DatapathId getDpid() { + return this.dpid; + } + + public Map<Object, Object> getAttributes() { + return this.attributes; + } + + public boolean isActive() { + return this.isActive; + } + + public Collection<IOFConnection> getConnections() { + return this.connections; + } + + public String getHandshakeState() { + return this.handshakeState; + } + + public String getQuarantineReason() { + return this.quarantineReason; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java b/src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java new file mode 100644 index 0000000000000000000000000000000000000000..480ff2004e0eae6f133fb79a94adc318b6b57cf4 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java @@ -0,0 +1,45 @@ +package net.floodlightcontroller.core.rest; + +import org.projectfloodlight.openflow.protocol.OFTableStatsEntry; +import org.projectfloodlight.openflow.types.TableId; +import org.projectfloodlight.openflow.types.U64; + +public class TableStatistics { + + private final TableId tableId; + private final long activeCount; + private final U64 lookupCount; + private final U64 matchedCount; + + private TableStatistics(TableId tableId, long activeCount, U64 lookupCount, U64 matchedCount) { + this.tableId = tableId; + this.activeCount = activeCount; + this.lookupCount = lookupCount; + this.matchedCount = matchedCount; + } + + public static TableStatistics of(TableId tableId, long activeCount, U64 lookupCount, U64 matchedCount) { + return new TableStatistics(tableId, activeCount, lookupCount, matchedCount); + } + + public static TableStatistics of(OFTableStatsEntry entry) { + return new TableStatistics(entry.getTableId(), + entry.getActiveCount(), entry.getLookupCount(), entry.getMatchedCount()); + } + + public TableId getTableId() { + return tableId; + } + + public long getActiveCount() { + return activeCount; + } + + public U64 getLookupCount() { + return lookupCount; + } + + public U64 getMatchedCount() { + return matchedCount; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java b/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java index 0e91bc9b488d6009eaaac15641aba1b0cde5a998..2f40532961b5912b2981f4ce5fbd75d668b1beb8 100644 --- a/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java +++ b/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java @@ -17,7 +17,7 @@ package net.floodlightcontroller.core.types; -import org.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFMessage; import net.floodlightcontroller.core.IOFSwitch; diff --git a/src/main/java/net/floodlightcontroller/core/util/URIUtil.java b/src/main/java/net/floodlightcontroller/core/util/URIUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..01a44ccf0cda6782ebbcaef9c5874361c4c272b0 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/util/URIUtil.java @@ -0,0 +1,10 @@ +package net.floodlightcontroller.core.util; + +import java.net.URI; + +public class URIUtil { + + public static URI createURI(String hostname, int port) { + return URI.create("tcp://" + hostname + ":" + port); + } +} diff --git a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java index c957e6356ba9833bb2b40e331881cccd528b40a1..cea740239ce1bfa20ad0d705135d507beaa188bb 100644 --- a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java @@ -25,10 +25,12 @@ import java.util.Map; import java.util.Set; import net.floodlightcontroller.core.IFloodlightProviderService; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFStatsReply; +import org.projectfloodlight.openflow.protocol.OFStatsType; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.util.HexString; import org.restlet.resource.Get; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,26 +52,26 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { public Map<String, Object> retrieveInternal(String statType) { HashMap<String, Object> model = new HashMap<String, Object>(); - OFStatisticsType type = null; + OFStatsType type = null; REQUESTTYPE rType = null; if (statType.equals("port")) { - type = OFStatisticsType.PORT; + type = OFStatsType.PORT; rType = REQUESTTYPE.OFSTATS; } else if (statType.equals("queue")) { - type = OFStatisticsType.QUEUE; + type = OFStatsType.QUEUE; rType = REQUESTTYPE.OFSTATS; } else if (statType.equals("flow")) { - type = OFStatisticsType.FLOW; + type = OFStatsType.FLOW; rType = REQUESTTYPE.OFSTATS; } else if (statType.equals("aggregate")) { - type = OFStatisticsType.AGGREGATE; + type = OFStatsType.AGGREGATE; rType = REQUESTTYPE.OFSTATS; } else if (statType.equals("desc")) { - type = OFStatisticsType.DESC; + type = OFStatsType.DESC; rType = REQUESTTYPE.OFSTATS; } else if (statType.equals("table")) { - type = OFStatisticsType.TABLE; + type = OFStatsType.TABLE; rType = REQUESTTYPE.OFSTATS; } else if (statType.equals("features")) { rType = REQUESTTYPE.OFFEATURES; @@ -80,11 +82,11 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { IFloodlightProviderService floodlightProvider = (IFloodlightProviderService)getContext().getAttributes(). get(IFloodlightProviderService.class.getCanonicalName()); - Set<Long> switchDpids = floodlightProvider.getAllSwitchDpids(); + Set<DatapathId> switchDpids = floodlightProvider.getAllSwitchDpids(); List<GetConcurrentStatsThread> activeThreads = new ArrayList<GetConcurrentStatsThread>(switchDpids.size()); List<GetConcurrentStatsThread> pendingRemovalThreads = new ArrayList<GetConcurrentStatsThread>(); GetConcurrentStatsThread t; - for (Long l : switchDpids) { + for (DatapathId l : switchDpids) { t = new GetConcurrentStatsThread(l, rType, type); activeThreads.add(t); t.start(); @@ -98,9 +100,9 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { for (GetConcurrentStatsThread curThread : activeThreads) { if (curThread.getState() == State.TERMINATED) { if (rType == REQUESTTYPE.OFSTATS) { - model.put(HexString.toHexString(curThread.getSwitchId()), curThread.getStatisticsReply()); + model.put(HexString.toHexString(curThread.getSwitchId().getLong()), curThread.getStatisticsReply()); } else if (rType == REQUESTTYPE.OFFEATURES) { - model.put(HexString.toHexString(curThread.getSwitchId()), curThread.getFeaturesReply()); + model.put(HexString.toHexString(curThread.getSwitchId().getLong()), curThread.getFeaturesReply()); } pendingRemovalThreads.add(curThread); } @@ -130,13 +132,13 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { } protected class GetConcurrentStatsThread extends Thread { - private List<OFStatistics> switchReply; - private long switchId; - private OFStatisticsType statType; + private List<OFStatsReply> switchReply; + private DatapathId switchId; + private OFStatsType statType; private REQUESTTYPE requestType; private OFFeaturesReply featuresReply; - public GetConcurrentStatsThread(long switchId, REQUESTTYPE requestType, OFStatisticsType statType) { + public GetConcurrentStatsThread(DatapathId switchId, REQUESTTYPE requestType, OFStatsType statType) { this.switchId = switchId; this.requestType = requestType; this.statType = statType; @@ -144,7 +146,7 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { this.featuresReply = null; } - public List<OFStatistics> getStatisticsReply() { + public List<OFStatsReply> getStatisticsReply() { return switchReply; } @@ -152,7 +154,7 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { return featuresReply; } - public long getSwitchId() { + public DatapathId getSwitchId() { return switchId; } diff --git a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java index eeaebe22c38aafb04834f2bac82e51be991e21be..457cc91c20fc15d854abeb148eccc27daef1c2d1 100644 --- a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java @@ -23,14 +23,16 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Collection; +import java.util.Set; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.ImmutablePort; import net.floodlightcontroller.util.FilterIterator; -import org.openflow.protocol.OFPhysicalPort; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFCapabilities; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.protocol.OFActionType; import org.restlet.data.Form; import org.restlet.data.Status; import org.restlet.resource.Get; @@ -52,7 +54,7 @@ public class ControllerSwitchesResource extends ServerResource { this.sw = sw; } - public int getActions() { + public Set<OFActionType> getActions() { return sw.getActions(); } @@ -83,11 +85,11 @@ public class ControllerSwitchesResource extends ServerResource { return rv; } - public int getBuffers() { + public long getBuffers() { return sw.getBuffers(); } - public int getCapabilities() { + public Set<OFCapabilities> getCapabilities() { return sw.getCapabilities(); } @@ -114,8 +116,8 @@ public class ControllerSwitchesResource extends ServerResource { return addr.toString(); } - public Collection<OFPhysicalPort> getPorts() { - return ImmutablePort.ofPhysicalPortListOf(sw.getPorts()); + public Collection<OFPortDesc> getPorts() { + return sw.getPorts(); } } @@ -158,13 +160,13 @@ public class ControllerSwitchesResource extends ServerResource { (IFloodlightProviderService)getContext().getAttributes(). get(IFloodlightProviderService.class.getCanonicalName()); - Long switchDPID = null; + DatapathId switchDPID = null; Form form = getQuery(); String dpid = form.getFirstValue("dpid", true); if (dpid != null) { try { - switchDPID = HexString.toLong(dpid); + switchDPID = DatapathId.of(dpid); } catch (Exception e) { setStatus(Status.CLIENT_ERROR_BAD_REQUEST, DPID_ERROR); return null; diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java index 34aa2eaa763f2953fa6b03ad95a82c25683add11..f8f9ff0e643e369cd3e342ddd933a302b4340cae 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; import org.restlet.resource.Get; import net.floodlightcontroller.core.IFloodlightProviderService; @@ -47,8 +47,8 @@ public class SwitchCounterCategoriesResource extends CounterResourceBase { String layer = (String) getRequestAttributes().get("layer"); if (switchID.equalsIgnoreCase("all")) { - for (Long dpid : floodlightProvider.getAllSwitchDpids()) { - switchID = HexString.toHexString(dpid); + for (DatapathId dpid : floodlightProvider.getAllSwitchDpids()) { + switchID = dpid.toString(); getOneSwitchCounterCategoriesJson(model, switchID, counterName, layer); } diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java index 34755ea083536a430652842a231fd22944e27552..f078dd8c198687537a1a1365026b40400ab7bc95 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java @@ -22,7 +22,7 @@ import java.net.URLDecoder; import java.util.HashMap; import java.util.Map; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; import org.restlet.resource.Get; import net.floodlightcontroller.core.IFloodlightProviderService; @@ -46,8 +46,8 @@ public class SwitchCounterResource extends CounterResourceBase { if (switchID.equalsIgnoreCase("all")) { getOneSwitchCounterJson(model, ICounterStoreService.CONTROLLER_NAME, counterName); - for (Long dpid : floodlightProvider.getAllSwitchDpids()) { - switchID = HexString.toHexString(dpid); + for (DatapathId dpid : floodlightProvider.getAllSwitchDpids()) { + switchID = dpid.toString(); getOneSwitchCounterJson(model, switchID, counterName); } diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java index 6b4a46318fb7dbac07fd628ed23fcc44b8fb146a..aa48eb3c1c63deb2f603f0668ffe5edc1999dd95 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java @@ -26,17 +26,23 @@ import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.annotations.LogMessageDoc; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFStatisticsRequest; -import org.openflow.protocol.statistics.OFAggregateStatisticsRequest; -import org.openflow.protocol.statistics.OFFlowStatisticsRequest; -import org.openflow.protocol.statistics.OFPortStatisticsRequest; -import org.openflow.protocol.statistics.OFQueueStatisticsRequest; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; +import org.projectfloodlight.openflow.protocol.OFMatch; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFAggregateStatsRequest; +import org.projectfloodlight.openflow.protocol.OFAggregateStatsReply; +import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; +import org.projectfloodlight.openflow.protocol.OFPortStatsRequest; +import org.projectfloodlight.openflow.protocol.OFQueueStatsRequest; +import org.projectfloodlight.openflow.protocol.OFStatsType; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFStatsReply; +import org.projectfloodlight.openflow.protocol.OFStatsRequest; +import org.projectfloodlight.openflow.types.DatapathId; import org.restlet.resource.ResourceException; import org.restlet.resource.ServerResource; import org.slf4j.Logger; @@ -67,21 +73,34 @@ public class SwitchResourceBase extends ServerResource { "from the switch", recommendation=LogMessageDoc.CHECK_SWITCH + " " + LogMessageDoc.GENERIC_ACTION) - protected List<OFStatistics> getSwitchStatistics(long switchId, - OFStatisticsType statType) { + protected List<OFStatsReply> getSwitchStatistics(DatapathId switchId, + OFStatsType statType) { IFloodlightProviderService floodlightProvider = (IFloodlightProviderService)getContext().getAttributes(). get(IFloodlightProviderService.class.getCanonicalName()); IOFSwitch sw = floodlightProvider.getSwitch(switchId); - Future<List<OFStatistics>> future; - List<OFStatistics> values = null; - if (sw != null) { - OFStatisticsRequest req = new OFStatisticsRequest(); - req.setStatisticType(statType); + + OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); + OFFlowStatsRequest flowStatsRequest = factory.buildFlowStatsRequest() + .build(); + + Future<List<OFFlowStatsReply>> future = sw.queryStatistics(flowStatsRequest); + return future.get(); + + + sw.get + + Future<List<OFStatsReply>> future; + List<OFStatsReply> values = null; + if (sw != null) + { + OFFactory + OFStatsRequest<> req = new OFFactory. + req.cre(statType); int requestLength = req.getLengthU(); - if (statType == OFStatisticsType.FLOW) { - OFFlowStatisticsRequest specificReq = new OFFlowStatisticsRequest(); + if (statType == OFStatsType.FLOW) { + OFStatsRequest specificReq = new OFFlowStatisticsRequest(); OFMatch match = new OFMatch(); match.setWildcards(0xffffffff); specificReq.setMatch(match); diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java index e6d66e2c24db29bad055be5d9a0132778e7ffe87..d7b4c01290368ce9b89b5a36c05c2aa236219926 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java @@ -18,7 +18,7 @@ package net.floodlightcontroller.core.web; import java.util.HashMap; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; import org.restlet.resource.ServerResource; import net.floodlightcontroller.core.IFloodlightProviderService; @@ -53,7 +53,7 @@ public class SwitchRoleResource extends ServerResource { return model; } - Long dpid = HexString.toLong(switchId); + DatapathId dpid = DatapathId.of(switchId); IOFSwitch sw = floodlightProvider.getSwitch(dpid); if (sw == null) return null; diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java index 57771f718bfa51295220deb2a3d9e0e88c4223e3..a70d120ae59ff618d8ae57a3b59601cb2e66bbec 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java @@ -20,7 +20,8 @@ package net.floodlightcontroller.core.web; import java.util.HashMap; import java.util.Map; -import org.openflow.protocol.statistics.OFStatisticsType; +import org.projectfloodlight.openflow.protocol.OFStatsType; +import org.projectfloodlight.openflow.types.DatapathId; import org.restlet.resource.Get; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,17 +43,17 @@ public class SwitchStatisticsResource extends SwitchResourceBase { String statType = (String) getRequestAttributes().get("statType"); if (statType.equals("port")) { - values = getSwitchStatistics(switchId, OFStatisticsType.PORT); + values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.PORT); } else if (statType.equals("queue")) { - values = getSwitchStatistics(switchId, OFStatisticsType.QUEUE); + values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.QUEUE); } else if (statType.equals("flow")) { - values = getSwitchStatistics(switchId, OFStatisticsType.FLOW); + values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.FLOW); } else if (statType.equals("aggregate")) { - values = getSwitchStatistics(switchId, OFStatisticsType.AGGREGATE); + values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.AGGREGATE); } else if (statType.equals("desc")) { - values = getSwitchStatistics(switchId, OFStatisticsType.DESC); + values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.DESC); } else if (statType.equals("table")) { - values = getSwitchStatistics(switchId, OFStatisticsType.TABLE); + values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.TABLE); } else if (statType.equals("features")) { values = getSwitchFeaturesReply(switchId); } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java index ce4d3ba3c51480ad3ab3b488c398727efb6d85b4..f5f3aea8c93f9a5769ad3eb8aa536755cf83e802 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java @@ -23,7 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.util.HexString; /** * Serialize a MAC as colon-separated hexadecimal diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java index 6df067ead245a209b12ce20347c237913a8f7b29..d07a254680074dc53bcd4095bf7dca98b39253e0 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java @@ -23,7 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.util.HexString; /** * Serialize a DPID as colon-separated hexadecimal diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java index c797681edf2e8779365293188e89f51b9b4c30a1..c7ea09b8364fa9b6e740da82b2a3f55ec6458fb8 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java @@ -23,7 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.util.HexString; /** * Serialize a MAC as colon-separated hexadecimal diff --git a/src/main/java/net/floodlightcontroller/counter/CounterStore.java b/src/main/java/net/floodlightcontroller/counter/CounterStore.java index bfe3b963f82b61bc0529005e4edd5b1f0b4d5164..d3067e60d5a75ec31e3b5ae911a3f5c8633e6137 100644 --- a/src/main/java/net/floodlightcontroller/counter/CounterStore.java +++ b/src/main/java/net/floodlightcontroller/counter/CounterStore.java @@ -24,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; + import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; @@ -33,8 +34,10 @@ import net.floodlightcontroller.counter.CounterValue.CounterType; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.DatapathId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,12 +72,12 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { } protected class CounterKeyTuple { - byte msgType; - long dpid; + OFType msgType; + DatapathId dpid; short l3type; byte l4type; - public CounterKeyTuple(byte msgType, long dpid, short l3type, byte l4type){ + public CounterKeyTuple(OFType msgType, DatapathId dpid, short l3type, byte l4type){ this.msgType = msgType; this.dpid = dpid; this.l3type = l3type; @@ -99,8 +102,8 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { public int hashCode() { final int prime = 283; int result = 1; - result = prime * result + msgType; - result = prime * result + (int) (dpid ^ (dpid >>> 32)); + result = prime * result + msgType.hashCode(); + result = prime * result + (int) (dpid.getLong() ^ (dpid.getLong() >>> 32)); result = prime * result + l3type; result = prime * result + l4type; return result; @@ -155,7 +158,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { @Override public void updatePacketInCountersLocal(IOFSwitch sw, OFMessage m, Ethernet eth) { - if (((OFPacketIn)m).getPacketData().length <= 0) { + if (((OFPacketIn)m).getData().length <= 0) { return; } CounterKeyTuple countersKey = this.getCountersKey(sw, m, eth); @@ -291,7 +294,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { //******************************* protected CounterKeyTuple getCountersKey(IOFSwitch sw, OFMessage m, Ethernet eth) { - byte mtype = m.getType().getTypeValue(); + OFType mtype = m.getType(); short l3type = 0; byte l4type = 0; @@ -322,7 +325,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { int l3type = eth.getEtherType() & 0xffff; String switchIdHex = sw.getStringId(); String etherType = String.format("%04x", eth.getEtherType()); - String packetName = m.getType().toClass().getName(); + String packetName = m.getType().getClass().getName(); packetName = packetName.substring(packetName.lastIndexOf('.')+1); // L2 Type @@ -470,7 +473,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService { /* String values for names */ String switchIdHex = sw.getStringId(); - String packetName = m.getType().toClass().getName(); + String packetName = m.getType().getClass().getName(); packetName = packetName.substring(packetName.lastIndexOf('.')+1); String controllerFMCounterName = diff --git a/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java b/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java index c0cbd55916086103bb4df820ca1b33974ed3dcca..79bf4548d6e6a6fc677eb3ebd5da3c2918808e55 100644 --- a/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java +++ b/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java @@ -19,7 +19,7 @@ package net.floodlightcontroller.counter; import java.util.List; import java.util.Map; -import org.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFMessage; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.IFloodlightService; diff --git a/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java b/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java index bdcc690b349c4497d8ca7b645b23a03d3af2ce85..eff67dcacfa1a85b48c8fdaf820250046310912e 100644 --- a/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java +++ b/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFMessage; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.FloodlightModuleContext; diff --git a/src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java b/src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java new file mode 100644 index 0000000000000000000000000000000000000000..8da964aa2d4c203801de60af38a968aacd52ae30 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java @@ -0,0 +1,338 @@ +package net.floodlightcontroller.debugcounter; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.TreeMap; +import java.util.regex.Pattern; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; + +/** + * A node in the counter hierarchy tree. We use a single tree and "merge" the + * counter modules into this single tree. + * + * <li> Adding modules or counters to the tree must happen at the root of the tree. + * <li> The root and the first level of the tree (root and module) are a shim + * layers that con't have an actual counter value. We represent this with a + * null counter. + * + * @author gregor + */ +class CounterNode implements Iterable<DebugCounterImpl> { + private static final String QUOTED_SEP = Pattern.quote("/"); + + /** path/hierarchy of this counter without leading /. An empty string + * represents the root. A string without a / is a module name + */ + private final String hierarchy; + /** + * The path/hierarchy elements split into a list + */ + private final List<String> hierarchyElements; + /** + * The actual counter instance for this node. Can be null for + * root level and module level. + */ + private final DebugCounterImpl counter; + private final TreeMap<String,CounterNode> children = new TreeMap<>(); + + /** + * convert module name and counter hierarchy into list of + * hierarchy elements + * @param moduleName + * @param counterHierarchy + * @return + */ + static List<String> + getHierarchyElements(String moduleName, String counterHierarchy) { + DebugCounterServiceImpl.verifyModuleNameSanity(moduleName); + List<String> ret = new ArrayList<>(); + ret.add(moduleName); + if (counterHierarchy == null || counterHierarchy.isEmpty()) { + return ret; + } + for (String element: counterHierarchy.split(QUOTED_SEP)) { + ret.add(element); + } + return ret; + } + + private CounterNode(List<String> hierarchyElements, + DebugCounterImpl counter) { + super(); + this.hierarchyElements = ImmutableList.copyOf(hierarchyElements); + this.hierarchy = Joiner.on("/").join(hierarchyElements); + this.counter = counter; + } + + /** + * Create a new counter hierarchy tree and return the root + * @return + */ + public static CounterNode newTree() { + return new CounterNode(ImmutableList.<String>of(), null); + } + + /** verify that this node is the root */ + private void verifyIsRoot() { + if (hierarchyElements.size() != 0) { + throw new IllegalStateException("This not is not the root. Can " + + "only call addCounter() on the root node. Current node: " + + hierarchy); + } + } + + + + /** + * return the full hierarchy as string, including module name + */ + @Nonnull + String getHierarchy() { + return hierarchy; + } + + /** + * @return the list of hierarchy elements for this node + */ + @Nonnull + List<String> getHierarchyElements() { + return hierarchyElements; + } + + /** + * @return this node's counters + */ + @Nullable + DebugCounterImpl getCounter() { + return counter; + } + + /** + * Reset this counter all counter below it in the hierarchy + */ + void resetHierarchy() { + for (DebugCounterImpl cur: this) { + cur.reset(); + } + } + + /** + * Return an Iterable over all DebugCounterImpls at and below this + * node. Note we return an Iterable<DebugCounterImpls> not + * Iterable<IDebugCounter> on purpose. + * @return + */ + Iterable<DebugCounterImpl> getCountersInHierarchy() { + return this; + } + + + /** + * Lookup the CounterNode identified by the hieraryElements if it exists. + * Returns null if no such CounterNode is found. Must only be called on + * the root of the tree. + * @param hierarchyElements + * @return + */ + CounterNode lookup(List<String> hierarchyElements) { + CounterNode cur = this; + for (String element: hierarchyElements) { + cur = cur.children.get(element); + if (cur == null) { + break; + } + } + return cur; + } + + /** + * Add the given moduleName to the tree. Can only be called on the root. + * If the module already exists, the all counters of the module will + * be reset. + * @param moduleName + * @return true if the module was newly added, false if the module already + * existed + */ + boolean addModule(@Nonnull String moduleName) { + verifyIsRoot(); + if (children.containsKey(moduleName)) { + children.get(moduleName).resetHierarchy(); + return false; + } else { + CounterNode newNode = + new CounterNode(ImmutableList.of(moduleName), null); + children.put(moduleName, newNode); + return true; + } + } + + /** + * Add the given Counter to the hierarchy. If the counterHierarcy already + * exists, reset the hierarchy + * @param counter + * @return null if the counterHierarchy is newly registered, otherwise + * returns the already registered DebugCounterImpl instance + * @throws IllegalArgumentException if the parent of the counter does not + * yet exist + */ + @Nullable + DebugCounterImpl addCounter(@Nonnull DebugCounterImpl counter) { + verifyIsRoot(); + ArrayList<String> path = new ArrayList<>(); + path.add(counter.getModuleName()); + for (String element: counter.getCounterHierarchy().split(QUOTED_SEP)) { + path.add(element); + } + String newCounterName = path.get(path.size()-1); + + CounterNode parent = lookup(path.subList(0, path.size()-1)); + if (parent == null) { + throw new IllegalArgumentException("Missing hierarchy level for " + + "counter: " + counter.getModuleName() + " " + + counter.getCounterHierarchy()); + } + if (parent.children.containsKey(newCounterName)) { + CounterNode old = parent.children.get(newCounterName); + // FIXME: we should check that old and new has the same + // description and meta-data, otherwise we should probably thrown + // and exception and refuse the operation. + old.resetHierarchy(); + return old.counter; + } else { + CounterNode newNode = new CounterNode(path, counter); + parent.children.put(newCounterName, newNode); + return counter; + } + } + + + /** + * Iterator over the counters in the counter hierarchy. + * Iteration order is a pre-order tree walk. Children of a node are + * visited in sorted order. + * @author gregor + */ + private final static class CounterIterator implements Iterator<DebugCounterImpl> { + // NOTE: since some counters + ArrayDeque<CounterNode> stack = new ArrayDeque<>(); + CounterNode curNode = null; + private CounterIterator(CounterNode root) { + stack.push(root); + gotoNextNode(); + } + + private void gotoNextNode() { + while (true) { + curNode = null; + if (stack.isEmpty()) { + break; + } + curNode = stack.pop(); + for (CounterNode child: curNode.children.descendingMap().values()) { + stack.push(child); + } + if (curNode.counter != null) { + break; + } + } + } + + @Override + public boolean hasNext() { + return curNode != null; + } + + @Override + public DebugCounterImpl next() { + if (curNode == null) { + throw new NoSuchElementException(); + } + DebugCounterImpl ret = curNode.counter; + gotoNextNode(); + return ret; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public Iterator<DebugCounterImpl> iterator() { + return new CounterIterator(this); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((children == null) ? 0 : children.hashCode()); + result = prime * result + + ((counter == null) ? 0 : counter.hashCode()); + result = prime * result + + ((hierarchy == null) ? 0 : hierarchy.hashCode()); + result = prime + * result + + ((hierarchyElements == null) ? 0 + : hierarchyElements.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + CounterNode other = (CounterNode) obj; + if (children == null) { + if (other.children != null) return false; + } else if (!children.equals(other.children)) return false; + if (counter == null) { + if (other.counter != null) return false; + } else if (!counter.equals(other.counter)) return false; + if (hierarchy == null) { + if (other.hierarchy != null) return false; + } else if (!hierarchy.equals(other.hierarchy)) return false; + if (hierarchyElements == null) { + if (other.hierarchyElements != null) return false; + } else if (!hierarchyElements.equals(other.hierarchyElements)) + return false; + return true; + } + + @Override + public String toString() { + return toString(0); + } + + public String toString(int indent) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < indent; i++) { + builder.append(" "); + } + builder.append("hierarchy="); + builder.append(hierarchy); + builder.append(", counter="); + builder.append(counter); + builder.append(", children="); + builder.append(children.keySet()); + builder.append("\n"); + for (CounterNode child: children.values()) { + builder.append(child.toString(indent + 3)); + } + return builder.toString(); + } + + + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java deleted file mode 100644 index 5bb1ce16757a4faa363205c346887ad1fbbc0d3e..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java +++ /dev/null @@ -1,741 +0,0 @@ -package net.floodlightcontroller.debugcounter; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Sets; - -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.debugcounter.web.DebugCounterRoutable; -import net.floodlightcontroller.restserver.IRestApiService; - -/** - * This class implements a central store for all counters used for debugging the - * system. For counters based on traffic-type, see ICounterStoreService. - * - * @author Saurav - */ -public class DebugCounter implements IFloodlightModule, IDebugCounterService { - protected static Logger log = LoggerFactory.getLogger(DebugCounter.class); - - /** - * registered counters need a counter id - */ - protected AtomicInteger counterIdCounter = new AtomicInteger(); - - /** - * The counter value - */ - protected class MutableLong { - long value = 0; - public void increment() { value += 1; } - public void increment(long incr) { value += incr; } - public long get() { return value; } - public void set(long val) { value = val; } - } - - /** - * protected class to store counter information - */ - public static class CounterInfo { - String moduleCounterHierarchy; - String counterDesc; - CounterType ctype; - String moduleName; - String counterHierarchy; - int counterId; - boolean enabled; - String[] metaData; - - public CounterInfo(int counterId, boolean enabled, - String moduleName, String counterHierarchy, - String desc, CounterType ctype, String... metaData) { - this.moduleCounterHierarchy = moduleName + "/" + counterHierarchy; - this.moduleName = moduleName; - this.counterHierarchy = counterHierarchy; - this.counterDesc = desc; - this.ctype = ctype; - this.counterId = counterId; - this.enabled = enabled; - this.metaData = metaData; - } - - public String getModuleCounterHierarchy() { return moduleCounterHierarchy; } - public String getCounterDesc() { return counterDesc; } - public CounterType getCtype() { return ctype; } - public String getModuleName() { return moduleName; } - public String getCounterHierarchy() { return counterHierarchy; } - public int getCounterId() { return counterId; } - public boolean isEnabled() { return enabled; } - public String[] getMetaData() { return metaData; } - } - - //****************** - // Global stores - //****************** - - /** - * Counter info for a debug counter - */ - public class DebugCounterInfo { - CounterInfo cinfo; - AtomicLong cvalue; - - public DebugCounterInfo(CounterInfo cinfo) { - this.cinfo = cinfo; - this.cvalue = new AtomicLong(); - } - public CounterInfo getCounterInfo() { - return cinfo; - } - public Long getCounterValue() { - return cvalue.get(); - } - } - - /** - * Global debug-counter storage across all threads. These are - * updated from the local per thread counters by the flush counters method. - */ - protected static DebugCounterInfo[] allCounters = - new DebugCounterInfo[MAX_COUNTERS]; - - - /** - * per module counters, indexed by the module name and storing three levels - * of Counter information in the form of CounterIndexStore - */ - protected ConcurrentHashMap<String, ConcurrentHashMap<String, CounterIndexStore>> - moduleCounters = new ConcurrentHashMap<String, - ConcurrentHashMap<String, - CounterIndexStore>>(); - - protected class CounterIndexStore { - int index; - Map<String, CounterIndexStore> nextLevel; - - public CounterIndexStore(int index, Map<String,CounterIndexStore> cis) { - this.index = index; - this.nextLevel = cis; - } - } - - /** - * fast global cache for counter ids that are currently active - */ - protected Set<Integer> currentCounters = Collections.newSetFromMap( - new ConcurrentHashMap<Integer,Boolean>()); - - //****************** - // Thread local stores - //****************** - - /** - * Thread local storage of counter info - */ - protected class LocalCounterInfo { - boolean enabled; - MutableLong cvalue; - - public LocalCounterInfo(boolean enabled) { - this.enabled = enabled; - this.cvalue = new MutableLong(); - } - } - - /** - * Thread local debug counters used for maintaining counters local to a thread. - */ - protected final ThreadLocal<LocalCounterInfo[]> threadlocalCounters = - new ThreadLocal<LocalCounterInfo[]>() { - @Override - protected LocalCounterInfo[] initialValue() { - return new LocalCounterInfo[MAX_COUNTERS]; - } - }; - - /** - * Thread local cache for counter ids that are currently active. - */ - protected final ThreadLocal<Set<Integer>> threadlocalCurrentCounters = - new ThreadLocal<Set<Integer>>() { - @Override - protected Set<Integer> initialValue() { - return new HashSet<Integer>(); - } - }; - - //******************************* - // IDebugCounter - //******************************* - - protected class CounterImpl implements IDebugCounter { - private final int counterId; - - public CounterImpl(int counterId) { - this.counterId = counterId; - } - - @Override - public void updateCounterWithFlush() { - if (!validCounterId()) return; - updateCounter(counterId, 1, true); - } - - @Override - public void updateCounterNoFlush() { - if (!validCounterId()) return; - updateCounter(counterId, 1, false); - } - - @Override - public void updateCounterWithFlush(int incr) { - if (!validCounterId()) return; - updateCounter(counterId, incr, true); - } - - @Override - public void updateCounterNoFlush(int incr) { - if (!validCounterId()) return; - updateCounter(counterId, incr, false); - } - - @Override - public long getCounterValue() { - if (!validCounterId()) return -1; - return allCounters[counterId].cvalue.get(); - } - - private boolean validCounterId() { - if (counterId < 0 || counterId >= MAX_COUNTERS) { - log.error("Invalid counterId invoked"); - return false; - } - return true; - } - - } - - //******************************* - // IDebugCounterService - //******************************* - - @Override - public IDebugCounter registerCounter(String moduleName, String counterHierarchy, - String counterDescription, CounterType counterType, - String... metaData) - throws MaxCountersRegistered, MaxHierarchyRegistered, - MissingHierarchicalLevel { - // check if counter already exists - if (!moduleCounters.containsKey(moduleName)) { - moduleCounters.putIfAbsent(moduleName, - new ConcurrentHashMap<String, CounterIndexStore>()); - } - RetCtrInfo rci = getCounterId(moduleName, counterHierarchy); - if (rci.allLevelsFound) { - // counter exists - log.info("Counter exists for {}/{} -- resetting counters", moduleName, - counterHierarchy); - resetCounterHierarchy(moduleName, counterHierarchy); - return new CounterImpl(rci.ctrIds[rci.foundUptoLevel-1]); - } - // check for validity of counter - if (rci.levels.length > MAX_HIERARCHY) { - String err = "Registry of counterHierarchy " + counterHierarchy + - " exceeds max hierachy " + MAX_HIERARCHY + ".. aborting"; - throw new MaxHierarchyRegistered(err); - } - if (rci.foundUptoLevel < rci.levels.length-1) { - String needToRegister = ""; - for (int i=0; i<=rci.foundUptoLevel; i++) { - needToRegister += rci.levels[i]; - } - String err = "Attempting to register hierarchical counterHierarchy " + - counterHierarchy + " but parts of hierarchy missing. " + - "Please register " + needToRegister + " first"; - throw new MissingHierarchicalLevel(err); - } - - // get a new counter id - int counterId = counterIdCounter.getAndIncrement(); - if (counterId >= MAX_COUNTERS) { - throw new MaxCountersRegistered("max counters reached"); - } - // create storage for counter - boolean enabled = (counterType == CounterType.ALWAYS_COUNT) ? true : false; - CounterInfo ci = new CounterInfo(counterId, enabled, moduleName, - counterHierarchy, counterDescription, - counterType, metaData); - allCounters[counterId] = new DebugCounterInfo(ci); - - // account for the new counter in the module counter hierarchy - addToModuleCounterHierarchy(moduleName, counterId, rci); - - // finally add to active counters - if (enabled) { - currentCounters.add(counterId); - } - return new CounterImpl(counterId); - } - - private void updateCounter(int counterId, int incr, boolean flushNow) { - if (counterId < 0 || counterId >= MAX_COUNTERS) return; - - LocalCounterInfo[] thiscounters = this.threadlocalCounters.get(); - if (thiscounters[counterId] == null) { - // seeing this counter for the first time in this thread - create local - // store by consulting global store - DebugCounterInfo dc = allCounters[counterId]; - if (dc != null) { - thiscounters[counterId] = new LocalCounterInfo(dc.cinfo.enabled); - if (dc.cinfo.enabled) { - Set<Integer> thisset = this.threadlocalCurrentCounters.get(); - thisset.add(counterId); - } - } else { - log.error("updateCounter seen locally for counter {} but no global" - + "storage exists for it yet .. not updating", counterId); - return; - } - } - - // update local store if enabled locally for updating - LocalCounterInfo lc = thiscounters[counterId]; - if (lc.enabled) { - lc.cvalue.increment(incr); - if (flushNow) { - DebugCounterInfo dc = allCounters[counterId]; - if (dc.cinfo.enabled) { - // globally enabled - flush now - dc.cvalue.addAndGet(lc.cvalue.get()); - lc.cvalue.set(0); - } else { - // global counter is disabled - don't flush, disable locally - lc.enabled = false; - Set<Integer> thisset = this.threadlocalCurrentCounters.get(); - thisset.remove(counterId); - } - } - } - } - - @Override - public void flushCounters() { - LocalCounterInfo[] thiscounters = this.threadlocalCounters.get(); - Set<Integer> thisset = this.threadlocalCurrentCounters.get(); - ArrayList<Integer> temp = new ArrayList<Integer>(); - - for (int counterId : thisset) { - LocalCounterInfo lc = thiscounters[counterId]; - if (lc.cvalue.get() > 0) { - DebugCounterInfo dc = allCounters[counterId]; - if (dc.cinfo.enabled) { - // globally enabled - flush now - dc.cvalue.addAndGet(lc.cvalue.get()); - lc.cvalue.set(0); - } else { - // global counter is disabled - don't flush, disable locally - lc.enabled = false; - temp.add(counterId); - } - } - } - for (int cId : temp) { - thisset.remove(cId); - } - - // At this point it is possible that the thread-local set does not - // include a counter that has been enabled and is present in the global set. - // We need to sync thread-local currently enabled set of counterIds with - // the global set. - Sets.SetView<Integer> sv = Sets.difference(currentCounters, thisset); - for (int counterId : sv) { - if (thiscounters[counterId] != null) { - thiscounters[counterId].enabled = true; - thisset.add(counterId); - } - } - } - - @Override - public void resetCounterHierarchy(String moduleName, String counterHierarchy) { - RetCtrInfo rci = getCounterId(moduleName, counterHierarchy); - if (!rci.allLevelsFound) { - String missing = rci.levels[rci.foundUptoLevel]; - log.error("Cannot reset counter hierarchy - missing counter {}", missing); - return; - } - // reset at this level - allCounters[rci.ctrIds[rci.foundUptoLevel-1]].cvalue.set(0); - // reset all levels below - ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci); - for (int index : resetIds) { - allCounters[index].cvalue.set(0); - } - } - - @Override - public void resetAllCounters() { - RetCtrInfo rci = new RetCtrInfo(); - rci.levels = "".split("/"); - for (String moduleName : moduleCounters.keySet()) { - ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci); - for (int index : resetIds) { - allCounters[index].cvalue.set(0); - } - } - } - - @Override - public void resetAllModuleCounters(String moduleName) { - Map<String, CounterIndexStore> target = moduleCounters.get(moduleName); - RetCtrInfo rci = new RetCtrInfo(); - rci.levels = "".split("/"); - - if (target != null) { - ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci); - for (int index : resetIds) { - allCounters[index].cvalue.set(0); - } - } else { - if (log.isDebugEnabled()) - log.debug("No module found with name {}", moduleName); - } - } - - @Override - public void enableCtrOnDemand(String moduleName, String counterHierarchy) { - RetCtrInfo rci = getCounterId(moduleName, counterHierarchy); - if (!rci.allLevelsFound) { - String missing = rci.levels[rci.foundUptoLevel]; - log.error("Cannot enable counter - counter not found {}", missing); - return; - } - // enable specific counter - DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]]; - dc.cinfo.enabled = true; - currentCounters.add(dc.cinfo.counterId); - } - - @Override - public void disableCtrOnDemand(String moduleName, String counterHierarchy) { - RetCtrInfo rci = getCounterId(moduleName, counterHierarchy); - if (!rci.allLevelsFound) { - String missing = rci.levels[rci.foundUptoLevel]; - log.error("Cannot disable counter - counter not found {}", missing); - return; - } - // disable specific counter - DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]]; - if (dc.cinfo.ctype == CounterType.COUNT_ON_DEMAND) { - dc.cinfo.enabled = false; - dc.cvalue.set(0); - currentCounters.remove(dc.cinfo.counterId); - } - } - - @Override - public List<DebugCounterInfo> getCounterHierarchy(String moduleName, - String counterHierarchy) { - RetCtrInfo rci = getCounterId(moduleName, counterHierarchy); - if (!rci.allLevelsFound) { - String missing = rci.levels[rci.foundUptoLevel]; - log.error("Cannot fetch counter - counter not found {}", missing); - return Collections.emptyList(); - } - ArrayList<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>(); - // get counter and all below it - DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]]; - dcilist.add(dc); - ArrayList<Integer> belowIds = getHierarchyBelow(moduleName, rci); - for (int index : belowIds) { - dcilist.add(allCounters[index]); - } - return dcilist; - } - - @Override - public List<DebugCounterInfo> getAllCounterValues() { - List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>(); - RetCtrInfo rci = new RetCtrInfo(); - rci.levels = "".split("/"); - - for (String moduleName : moduleCounters.keySet()) { - ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci); - for (int index : resetIds) { - dcilist.add(allCounters[index]); - } - } - return dcilist; - } - - @Override - public List<DebugCounterInfo> getModuleCounterValues(String moduleName) { - List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>(); - RetCtrInfo rci = new RetCtrInfo(); - rci.levels = "".split("/"); - - if (moduleCounters.containsKey(moduleName)) { - ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci); - for (int index : resetIds) { - dcilist.add(allCounters[index]); - } - } - return dcilist; - } - - @Override - public boolean containsModuleCounterHierarchy(String moduleName, - String counterHierarchy) { - if (!moduleCounters.containsKey(moduleName)) return false; - RetCtrInfo rci = getCounterId(moduleName, counterHierarchy); - return rci.allLevelsFound; - } - - @Override - public boolean containsModuleName(String moduleName) { - return (moduleCounters.containsKey(moduleName)) ? true : false; - } - - @Override - public List<String> getModuleList() { - List<String> retval = new ArrayList<String>(); - retval.addAll(moduleCounters.keySet()); - return retval; - } - - @Override - public List<String> getModuleCounterList(String moduleName) { - if (!moduleCounters.containsKey(moduleName)) - return Collections.emptyList(); - - List<String> retval = new ArrayList<String>(); - RetCtrInfo rci = new RetCtrInfo(); - rci.levels = "".split("/"); - - ArrayList<Integer> cids = getHierarchyBelow(moduleName, rci); - for (int index : cids) { - retval.add(allCounters[index].cinfo.counterHierarchy); - } - return retval; - } - - //******************************* - // Internal Methods - //******************************* - - protected class RetCtrInfo { - boolean allLevelsFound; // counter indices found all the way down the hierarchy - boolean hierarchical; // true if counterHierarchy is hierarchical - int foundUptoLevel; - int[] ctrIds; - String[] levels; - - public RetCtrInfo() { - ctrIds = new int[MAX_HIERARCHY]; - for (int i=0; i<MAX_HIERARCHY; i++) { - ctrIds[i] = -1; - } - } - - @Override - public boolean equals(Object oth) { - if (!(oth instanceof RetCtrInfo)) return false; - RetCtrInfo other = (RetCtrInfo)oth; - if (other.allLevelsFound != this.allLevelsFound) return false; - if (other.hierarchical != this.hierarchical) return false; - if (other.foundUptoLevel != this.foundUptoLevel) return false; - if (!Arrays.equals(other.ctrIds, this.ctrIds)) return false; - if (!Arrays.equals(other.levels, this.levels)) return false; - return true; - } - - } - - protected RetCtrInfo getCounterId(String moduleName, String counterHierarchy) { - RetCtrInfo rci = new RetCtrInfo(); - Map<String, CounterIndexStore> templevel = moduleCounters.get(moduleName); - rci.levels = counterHierarchy.split("/"); - if (rci.levels.length > 1) rci.hierarchical = true; - if (templevel == null) { - log.error("moduleName {} does not exist in debugCounters", moduleName); - return rci; - } - - /* - if (rci.levels.length > MAX_HIERARCHY) { - // chop off all array elems greater that MAX_HIERARCHY - String[] temp = new String[MAX_HIERARCHY]; - System.arraycopy(rci.levels, 0, temp, 0, MAX_HIERARCHY); - rci.levels = temp; - } - */ - for (int i=0; i<rci.levels.length; i++) { - if (templevel != null) { - CounterIndexStore cis = templevel.get(rci.levels[i]) ; - if (cis == null) { - // could not find counterHierarchy part at this level - break; - } else { - rci.ctrIds[i] = cis.index; - templevel = cis.nextLevel; - rci.foundUptoLevel++; - if (i == rci.levels.length-1) { - rci.allLevelsFound = true; - } - } - } else { - // there are no more levels, which means that some part of the - // counterHierarchy has no corresponding map - break; - } - } - return rci; - } - - protected void addToModuleCounterHierarchy(String moduleName, int counterId, - RetCtrInfo rci) { - Map<String, CounterIndexStore> target = moduleCounters.get(moduleName); - if (target == null) return; - CounterIndexStore cis = null; - - for (int i=0; i<rci.foundUptoLevel; i++) { - cis = target.get(rci.levels[i]); - target = cis.nextLevel; - } - if (cis != null) { - if (cis.nextLevel == null) - cis.nextLevel = new ConcurrentHashMap<String, CounterIndexStore>(); - cis.nextLevel.put(rci.levels[rci.foundUptoLevel], - new CounterIndexStore(counterId, null)); - } else { - target.put(rci.levels[rci.foundUptoLevel], - new CounterIndexStore(counterId, null)); - } - } - - // given a partial hierarchical counter, return the rest of the hierarchy - protected ArrayList<Integer> getHierarchyBelow(String moduleName, RetCtrInfo rci) { - Map<String, CounterIndexStore> target = moduleCounters.get(moduleName); - CounterIndexStore cis = null; - ArrayList<Integer> retval = new ArrayList<Integer>(); - if (target == null) return retval; - - // get to the level given - for (int i=0; i<rci.foundUptoLevel; i++) { - cis = target.get(rci.levels[i]); - target = cis.nextLevel; - } - - if (target == null || rci.foundUptoLevel == MAX_HIERARCHY) { - // no more levels - return retval; - } else { - // recursively get all ids - getIdsAtLevel(target, retval, rci.foundUptoLevel+1); - } - - return retval; - } - - protected void getIdsAtLevel(Map<String, CounterIndexStore> hcy, - ArrayList<Integer> retval, int level) { - if (level > MAX_HIERARCHY) return; - if (hcy == null || retval == null) return; - - // Can return the counter names as well but for now ids are enough. - for (CounterIndexStore cistemp : hcy.values()) { - retval.add(cistemp.index); // value at this level - if (cistemp.nextLevel != null) { - getIdsAtLevel(cistemp.nextLevel, retval, level+1); - } - } - } - - protected void printAllCounterIds() { - log.info("<moduleCounterHierarchy>"); - Set<String> keys = moduleCounters.keySet(); - for (String key : keys) { - log.info("ModuleName: {}", key); - Map<String, CounterIndexStore> lev1 = moduleCounters.get(key); - for (String key1 : lev1.keySet()) { - CounterIndexStore cis1 = lev1.get(key1); - log.info(" L1 {}:{}", key1, new Object[] {cis1.index, cis1.nextLevel}); - if (cis1.nextLevel != null) { - Map<String, CounterIndexStore> lev2 = cis1.nextLevel; - for (String key2 : lev2.keySet()) { - CounterIndexStore cis2 = lev2.get(key2); - log.info(" L2 {}:{}", key2, new Object[] {cis2.index, - cis2.nextLevel}); - if (cis2.nextLevel != null) { - Map<String, CounterIndexStore> lev3 = cis2.nextLevel; - for (String key3 : lev3.keySet()) { - CounterIndexStore cis3 = lev3.get(key3); - log.info(" L3 {}:{}", key3, new Object[] {cis3.index, - cis3.nextLevel}); - } - } - } - } - } - } - log.info("<\\moduleCounterHierarchy>"); - } - - //******************************* - // IFloodlightModule - //******************************* - - @Override - public Collection<Class<? extends IFloodlightService>> getModuleServices() { - Collection<Class<? extends IFloodlightService>> l = - new ArrayList<Class<? extends IFloodlightService>>(); - l.add(IDebugCounterService.class); - return l; - } - - @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { - Map<Class<? extends IFloodlightService>, IFloodlightService> m = - new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); - m.put(IDebugCounterService.class, this); - return m; - } - - @Override - public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { - ArrayList<Class<? extends IFloodlightService>> deps = - new ArrayList<Class<? extends IFloodlightService>>(); - deps.add(IRestApiService.class); - return deps; - } - - @Override - public void init(FloodlightModuleContext context) throws FloodlightModuleException { - - } - - @Override - public void startUp(FloodlightModuleContext context) { - IRestApiService restService = - context.getServiceImpl(IRestApiService.class); - restService.addRestletRoutable(new DebugCounterRoutable()); - } - -} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c0aa316d953dc90a65c565f1d34719c8d19ddd5f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java @@ -0,0 +1,141 @@ +package net.floodlightcontroller.debugcounter; + +import java.util.Collection; +import java.util.concurrent.atomic.AtomicLong; + +import javax.annotation.Nonnull; + +import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + + +class DebugCounterImpl implements IDebugCounter { + private final String moduleName; + private final String counterHierarchy; + private final String description; + private final ImmutableSet<IDebugCounterService.MetaData> metaData; + + private final AtomicLong value = new AtomicLong(); + + + DebugCounterImpl(@Nonnull String moduleName, + @Nonnull String counterHierarchy, + @Nonnull String description, + @Nonnull Collection<MetaData> metaData) { + this.moduleName = moduleName; + this.counterHierarchy = counterHierarchy; + this.description = description; + this.metaData = Sets.immutableEnumSet(metaData); + } + + @Nonnull + String getModuleName() { + return moduleName; + } + + + @Nonnull + String getCounterHierarchy() { + return counterHierarchy; + } + + + @Nonnull + String getDescription() { + return description; + } + + @Nonnull + ImmutableSet<IDebugCounterService.MetaData> getMetaData() { + return metaData; + } + + public void reset() { + value.set(0); + } + + @Override + public void increment() { + value.incrementAndGet(); + } + + @Override + public void add(long increment) { + if (increment < 0) { + throw new IllegalArgumentException("increment must be > 0. Was " + + increment); + } + value.addAndGet(increment); + } + + @Override + public long getCounterValue() { + return value.get(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime + * result + + ((counterHierarchy == null) ? 0 + : counterHierarchy.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((metaData == null) ? 0 : metaData.hashCode()); + result = prime * result + + ((moduleName == null) ? 0 : moduleName.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + DebugCounterImpl other = (DebugCounterImpl) obj; + if (counterHierarchy == null) { + if (other.counterHierarchy != null) return false; + } else if (!counterHierarchy.equals(other.counterHierarchy)) + return false; + if (description == null) { + if (other.description != null) return false; + } else if (!description.equals(other.description)) return false; + if (metaData == null) { + if (other.metaData != null) return false; + } else if (!metaData.equals(other.metaData)) return false; + if (moduleName == null) { + if (other.moduleName != null) return false; + } else if (!moduleName.equals(other.moduleName)) return false; + if (value == null) { + if (other.value != null) return false; + } else if (value.get() != other.value.get()) return false; + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("["); + builder.append(moduleName); + builder.append(" "); + builder.append(counterHierarchy); + builder.append(", description="); + builder.append(description); + builder.append(", metaData="); + builder.append(metaData); + builder.append(", value="); + builder.append(value); + builder.append("]"); + return builder.toString(); + } + + + + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java new file mode 100644 index 0000000000000000000000000000000000000000..941802c31d4bd2b536002f0a094b6b781af78e32 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java @@ -0,0 +1,119 @@ +package net.floodlightcontroller.debugcounter; + +import java.util.Set; + +import javax.annotation.concurrent.Immutable; + +import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; + +/** + * Resource class for DebugCounter + * Serves the REST api with dynamic data + */ +@Immutable +public class DebugCounterResource { + + public static final String MODULE_NAME_PREDICATE = "modulename"; + public static final String HIERARCHY_PREDICATE = "hierarchy"; + private static final Joiner joiner = Joiner.on(", "); + + + private final Long counterValue; + private final String counterDesc; + private final String counterHierarchy; + private final String moduleName; + private final ImmutableSet<MetaData> metadata; + private final String metadataString; + + public DebugCounterResource(DebugCounterImpl counter) { + this.moduleName = counter.getModuleName(); + this.counterHierarchy = counter.getCounterHierarchy(); + this.counterDesc = counter.getDescription(); + this.metadata = counter.getMetaData(); + this.counterValue = counter.getCounterValue(); + this.metadataString = joiner.join(metadata); + } + + public Long getCounterValue() { + return counterValue; + } + + public String getCounterDesc() { + return counterDesc; + } + + public String getCounterHierarchy() { + return counterHierarchy; + } + + public String getModuleName() { + return moduleName; + } + + public Set<MetaData> getMetadata() { + return metadata; + } + + public String getMetadataString() { + return metadataString; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((counterDesc == null) ? 0 : counterDesc.hashCode()); + result = prime + * result + + ((counterHierarchy == null) ? 0 + : counterHierarchy.hashCode()); + result = prime * result + + ((counterValue == null) ? 0 : counterValue.hashCode()); + result = prime * result + + ((metadata == null) ? 0 : metadata.hashCode()); + result = prime + * result + + ((metadataString == null) ? 0 : metadataString.hashCode()); + result = prime * result + + ((moduleName == null) ? 0 : moduleName.hashCode()); + return result; + } + + /** + * Compare all fields, not only the "key" fields + */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + DebugCounterResource other = (DebugCounterResource) obj; + if (counterDesc == null) { + if (other.counterDesc != null) return false; + } else if (!counterDesc.equals(other.counterDesc)) return false; + if (counterHierarchy == null) { + if (other.counterHierarchy != null) return false; + } else if (!counterHierarchy.equals(other.counterHierarchy)) + return false; + if (counterValue == null) { + if (other.counterValue != null) return false; + } else if (!counterValue.equals(other.counterValue)) return false; + if (metadata == null) { + if (other.metadata != null) return false; + } else if (!metadata.equals(other.metadata)) return false; + if (metadataString == null) { + if (other.metadataString != null) return false; + } else if (!metadataString.equals(other.metadataString)) + return false; + if (moduleName == null) { + if (other.moduleName != null) return false; + } else if (!moduleName.equals(other.moduleName)) return false; + return true; + } + + +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java deleted file mode 100644 index 9edd47473a75564334c217b240002612d31e6219..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.floodlightcontroller.debugcounter; - -import org.restlet.resource.ResourceException; -import org.restlet.resource.ServerResource; - -public class DebugCounterResourceBase extends ServerResource { - - protected IDebugCounterService debugCounter; - - @Override - protected void doInit() throws ResourceException { - super.doInit(); - debugCounter = (IDebugCounterService)getContext().getAttributes(). - get(IDebugCounterService.class.getCanonicalName()); - } -} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..2e2fe499f8ff592cfc9837091f0cd22fbe6be4b2 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java @@ -0,0 +1,251 @@ +package net.floodlightcontroller.debugcounter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.GuardedBy; + +import org.projectfloodlight.core.IShutdownListener; +import org.projectfloodlight.core.IShutdownService; +import net.floodlightcontroller.core.module.FloodlightModuleContext; +import net.floodlightcontroller.core.module.IFloodlightModule; +import net.floodlightcontroller.core.module.IFloodlightService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DebugCounterServiceImpl implements IFloodlightModule, IDebugCounterService { + protected static final Logger logger = + LoggerFactory.getLogger(DebugCounterServiceImpl.class); + + /** + * The tree of counters. + */ + private final CounterNode root = CounterNode.newTree(); + + /** + * protects the counter hierarchy tree. The writeLock is required to + * change to hierarchy, i.e., adding nodes. The readLock is required + * to query the counters or to reset them. + */ + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + + static void verifyStringSanity(String str, String name) { + if (str == null) { + if (name == null) { + throw new NullPointerException(); + } else { + throw new NullPointerException(name + " must not be null"); + } + } + if (str.isEmpty()) { + if (name == null) { + throw new IllegalArgumentException(); + } else { + throw new IllegalArgumentException(name + " must not be empty"); + } + } + } + + static void verifyModuleNameSanity(String moduleName) { + verifyStringSanity(moduleName, "moduleName"); + if (moduleName.contains("/")) { + throw new IllegalArgumentException("moduleName must not contain /"); + } + } + + @Override + public boolean registerModule(String moduleName) { + verifyModuleNameSanity(moduleName); + lock.writeLock().lock(); + try { + return root.addModule(moduleName); + } finally { + lock.writeLock().unlock(); + } + } + + @Override + public IDebugCounter registerCounter(@Nonnull String moduleName, + @Nonnull String counterHierarchy, + @Nonnull String counterDescription, + @Nonnull MetaData... metaData) { + verifyModuleNameSanity(moduleName); + verifyStringSanity(counterHierarchy, "counterHierarchy"); + if (counterDescription == null) { + throw new Exception("counterDescription must not be null"); + } + if (metaData == null) { + // somebody passing in a null array. sigh. + throw new NullPointerException("metaData must not be null"); + } + DebugCounterImpl counter = + new DebugCounterImpl(moduleName, counterHierarchy, + counterDescription, + Arrays.asList(metaData)); + lock.writeLock().lock(); + try { + DebugCounterImpl oldCounter = root.addCounter(counter); + if (oldCounter != null && logger.isDebugEnabled()) { + logger.debug("Counter {} {} already registered. Resetting hierarchy", + moduleName, counterHierarchy); + } + return oldCounter; + } finally { + lock.writeLock().unlock(); + } + } + + @GuardedBy("lock.readLock") + private boolean resetInternal(List<String> hierarchyElements) { + CounterNode node = root.lookup(hierarchyElements); + if (node == null) { + return false; + } + node.resetHierarchy(); + return true; + } + + @Override + public boolean resetCounterHierarchy(String moduleName, + String counterHierarchy) { + verifyModuleNameSanity(moduleName); + verifyStringSanity(counterHierarchy, "counterHierarchy"); + lock.readLock().lock(); + try { + return resetInternal(CounterNode.getHierarchyElements(moduleName, counterHierarchy)); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public void resetAllCounters() { + lock.readLock().lock(); + try { + root.resetHierarchy(); + } finally { + lock.readLock().unlock(); + } + } + + + @Override + public boolean resetAllModuleCounters(String moduleName) { + verifyModuleNameSanity(moduleName); + lock.readLock().lock(); + try { + return resetInternal(Collections.singletonList(moduleName)); + } finally { + lock.readLock().unlock(); + } + } + + @GuardedBy("lock.readLock") + private List<DebugCounterResource> getCountersFromNode(CounterNode node) { + if (node == null) { + return Collections.emptyList(); + } + List<DebugCounterResource> ret = new ArrayList<>(); + for (DebugCounterImpl counter: node.getCountersInHierarchy()) { + ret.add(new DebugCounterResource(counter)); + } + return ret; + } + + @Override + public List<DebugCounterResource> + getCounterHierarchy(String moduleName, String counterHierarchy) { + verifyModuleNameSanity(moduleName); + verifyStringSanity(counterHierarchy, "counterHierarchy"); + List<String> hierarchyElements = + CounterNode.getHierarchyElements(moduleName, counterHierarchy); + lock.readLock().lock(); + try { + return getCountersFromNode(root.lookup(hierarchyElements)); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public List<DebugCounterResource> getAllCounterValues() { + lock.readLock().lock(); + try { + return getCountersFromNode(root); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public List<DebugCounterResource> getModuleCounterValues(String moduleName) { + verifyModuleNameSanity(moduleName); + List<String> hierarchyElements = Collections.singletonList(moduleName); + lock.readLock().lock(); + try { + return getCountersFromNode(root.lookup(hierarchyElements)); + } finally { + lock.readLock().unlock(); + } + } + + private class ShutdownListenenerDelegate implements IShutdownListener { + @Override + public void floodlightIsShuttingDown() { + for (DebugCounterResource counter: getAllCounterValues()) { + logger.info("Module {} counterHierarchy {} value {}", + counter.getModuleName(), + counter.getCounterHierarchy(), + counter.getCounterValue()); + } + } + } + + + //******************************* + // IFloodlightModule + //******************************* + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IDebugCounterService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); + m.put(IDebugCounterService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + ArrayList<Class<? extends IFloodlightService>> deps = + new ArrayList<Class<? extends IFloodlightService>>(); + deps.add(IShutdownService.class); + return deps; + } + + @Override + public void init(FloodlightModuleContext context) { + } + + @Override + public void startUp(FloodlightModuleContext context) { + IShutdownService shutdownService = + context.getServiceImpl(IShutdownService.class); + shutdownService.registerShutdownListener(new ShutdownListenenerDelegate()); + } + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java deleted file mode 100644 index dbde1854e9c6f7707e983eedf5bfe6fef299d7ec..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.floodlightcontroller.debugcounter; - -public interface IDebugCounter { - /** - * Increments the counter by 1 thread-locally, and immediately flushes to - * the global counter storage. This method should be used for counters that - * are updated outside the OF message processing pipeline. - */ - void updateCounterWithFlush(); - - /** - * Increments the counter by 1 thread-locally. Flushing to the global - * counter storage is delayed (happens with flushCounters() in IDebugCounterService), - * resulting in higher performance. This method should be used for counters - * updated in the OF message processing pipeline. - */ - void updateCounterNoFlush(); - - /** - * Increments the counter thread-locally by the 'incr' specified, and immediately - * flushes to the global counter storage. This method should be used for counters - * that are updated outside the OF message processing pipeline. - */ - void updateCounterWithFlush(int incr); - - /** - * Increments the counter thread-locally by the 'incr' specified. Flushing to the global - * counter storage is delayed (happens with flushCounters() in IDebugCounterService), - * resulting in higher performance. This method should be used for counters - * updated in the OF message processing pipeline. - */ - void updateCounterNoFlush(int incr); - - /** - * Retrieve the value of the counter from the global counter store - */ - long getCounterValue(); -} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java deleted file mode 100644 index 538e60dad148c600e3802b53271ed6e111d8f6b9..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java +++ /dev/null @@ -1,259 +0,0 @@ -package net.floodlightcontroller.debugcounter; - -import net.floodlightcontroller.core.module.IFloodlightService; -import net.floodlightcontroller.debugcounter.DebugCounter.DebugCounterInfo; - -import java.util.List; - -public interface IDebugCounterService extends IFloodlightService { - - /** - * Different counter types. Counters that are meant to be counted-on-demand - * need to be separately enabled/disabled. - */ - public enum CounterType { - ALWAYS_COUNT, - COUNT_ON_DEMAND - } - - /** - * Debug Counter Qualifiers - */ - public static final String CTR_MDATA_WARN = "warn"; - public static final String CTR_MDATA_ERROR = "error"; - - /** - * A limit on the maximum number of counters that can be created - */ - public static final int MAX_COUNTERS = 5000; - - /** - * Exception thrown when MAX_COUNTERS have been registered - */ - public class MaxCountersRegistered extends CounterException { - private static final long serialVersionUID = 3173747663719376745L; - String errormsg; - public MaxCountersRegistered(String errormsg) { - this.errormsg = errormsg; - } - @Override - public String getMessage() { - return this.errormsg; - } - } - /** - * Exception thrown when MAX_HIERARCHY has been reached - */ - public class MaxHierarchyRegistered extends CounterException { - private static final long serialVersionUID = 967431358683523871L; - String errormsg; - public MaxHierarchyRegistered(String errormsg) { - this.errormsg = errormsg; - } - @Override - public String getMessage() { - return this.errormsg; - } - } - /** - * Exception thrown when attempting to register a hierarchical counter - * where higher levels of the hierarchy have not been pre-registered - */ - public class MissingHierarchicalLevel extends CounterException { - private static final long serialVersionUID = 517315311533995739L; - String errormsg; - public MissingHierarchicalLevel(String errormsg) { - this.errormsg = errormsg; - } - @Override - public String getMessage() { - return this.errormsg; - } - } - - public class CounterException extends Exception { - private static final long serialVersionUID = 2219781500857866035L; - } - - /** - * maximum levels of hierarchy - * Example of moduleName/counterHierarchy: - * switch/00:00:00:00:01:02:03:04/pktin/drops where - * moduleName ==> "switch" and - * counterHierarchy of 3 ==> "00:00:00:00:01:02:03:04/pktin/drops" - */ - public static final int MAX_HIERARCHY = 3; - - /** - * All modules that wish to have the DebugCounterService count for them, must - * register their counters by making this call (typically from that module's - * 'startUp' method). The counter can then be updated, displayed, reset etc. - * using the registered moduleName and counterHierarchy. - * - * @param moduleName the name of the module which is registering the - * counter eg. linkdiscovery or controller or switch - * @param counterHierarchy the hierarchical counter name specifying all - * the hierarchical levels that come above it. - * For example: to register a drop counter for - * packet-ins from a switch, the counterHierarchy - * can be "00:00:00:00:01:02:03:04/pktin/drops" - * It is necessary that counters in hierarchical levels - * above have already been pre-registered - in this - * example: "00:00:00:00:01:02:03:04/pktin" and - * "00:00:00:00:01:02:03:04" - * @param counterDescription a descriptive string that gives more information - * of what the counter is measuring. For example, - * "Measures the number of incoming packets seen by - * this module". - * @param counterType One of CounterType. On-demand counter types - * need to be explicitly enabled/disabled using other - * methods in this API -- i.e. registering them is - * not enough to start counting. - * @param metaData variable arguments that qualify a counter - * eg. warn, error etc. - * @return IDebugCounter with update methods that can be - * used to update a counter. - * @throws MaxCountersRegistered - * @throws MaxHierarchyRegistered - * @throws MissingHierarchicalLevel - */ - public IDebugCounter registerCounter(String moduleName, String counterHierarchy, - String counterDescription, CounterType counterType, - String... metaData) - throws MaxCountersRegistered, MaxHierarchyRegistered, - MissingHierarchicalLevel; - - /** - * Flush all thread-local counter values (from the current thread) - * to the global counter store. This method is not intended for use by any - * module. It's typical usage is from floodlight core and it is meant - * to flush those counters that are updated in the packet-processing pipeline, - * typically with the 'updateCounterNoFlush" methods in IDebugCounter. - */ - public void flushCounters(); - - /** - * Resets the value of counters in the hierarchy to zero. Note that the reset - * applies to the level of counter hierarchy specified AND ALL LEVELS BELOW it - * in the hierarchy. - * For example: If a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops" - * specifying a reset hierarchy: "00:00:00:00:01:02:03:04" - * will reset all counters for the switch dpid specified; - * while specifying a reset hierarchy: ""00:00:00:00:01:02:03:04/pktin" - * will reset the pktin counter and all levels below it (like drops) - * for the switch dpid specified. - */ - void resetCounterHierarchy(String moduleName, String counterHierarchy); - - /** - * Resets the values of all counters in the system. - */ - public void resetAllCounters(); - - /** - * Resets the values of all counters belonging - * to a module with the given 'moduleName'. - */ - public void resetAllModuleCounters(String moduleName); - - /** - * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to - * enable counting on the counter. Note that this step is necessary to start - * counting for these counter types - merely registering the counter is not - * enough (as is the case for CounterType.ALWAYS_COUNT). Newly - * enabled counters start from an initial value of zero. - * - * Enabling a counter in a counterHierarchy enables only THAT counter. It - * does not enable any other part of the counterHierarchy. For example, if - * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the - * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then enabling - * the 'pktin' counter by specifying the counterHierarchy as - * "00:00:00:00:01:02:03:04/pktin" does NOT enable the 'drops' counter. - */ - public void enableCtrOnDemand(String moduleName, String counterHierarchy); - - /** - * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to - * enable counting on the counter. Note that disabling a counter results in a loss - * of the counter value. When re-enabled the counter will restart from zero. - * - * Disabling a counter in a counterHierarchy disables only THAT counter. It - * does not disable any other part of the counterHierarchy. For example, if - * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the - * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then disabling - * the 'pktin' counter by specifying the counterHierarchy as - * "00:00:00:00:01:02:03:04/pktin" does NOT disable the 'drops' counter. - */ - public void disableCtrOnDemand(String moduleName, String counterHierarchy); - - /** - * Get counter value and associated information for the specified counterHierarchy. - * Note that information on the level of counter hierarchy specified - * AND ALL LEVELS BELOW it in the hierarchy will be returned. - * - * For example, - * if a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", then - * specifying a counterHierarchy of "00:00:00:00:01:02:03:04/pktin" in the - * get call will return information on the 'pktin' as well as the 'drops' - * counters for the switch dpid specified. - * - * @return A list of DebugCounterInfo or an empty list if the counter - * could not be found - */ - public List<DebugCounterInfo> getCounterHierarchy(String moduleName, - String counterHierarchy); - - /** - * Get counter values and associated information for all counters in the - * system - * - * @return the list of values/info or an empty list - */ - public List<DebugCounterInfo> getAllCounterValues(); - - /** - * Get counter values and associated information for all counters associated - * with a module. - * - * @param moduleName - * @return the list of values/info or an empty list - */ - public List<DebugCounterInfo> getModuleCounterValues(String moduleName); - - /** - * Convenience method to figure out if the the given 'counterHierarchy' corresponds - * to a registered counterHierarchy for 'moduleName'. Note that the counter may or - * may not be enabled for counting, but if it is registered the method will - * return true. - * - * @param param - * @return false if moduleCounterHierarchy is not a registered counter - */ - public boolean containsModuleCounterHierarchy(String moduleName, - String counterHierarchy); - - /** - * Convenience method to figure out if the the given 'moduleName' corresponds - * to a registered moduleName or not. Note that the module may or may not have - * a counter enabled for counting, but if it is registered the method will - * return true. - * - * @param param - * @return false if moduleName is not a registered counter - */ - public boolean containsModuleName(String moduleName); - - /** - * Returns a list of moduleNames registered for debug counters or an empty - * list if no counters have been registered in the system - */ - public List<String> getModuleList(); - - /** - * Returns a list of all counters registered for a specific moduleName - * or a empty list - */ - public List<String> getModuleCounterList(String moduleName); - - -} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java b/src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java new file mode 100644 index 0000000000000000000000000000000000000000..3540519639911602788f965e52d2793f27d0f737 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java @@ -0,0 +1,115 @@ +package net.floodlightcontroller.debugcounter; + +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 org.projectfloodlight.core.module.FloodlightModuleContext; +import org.projectfloodlight.core.module.FloodlightModuleException; +import org.projectfloodlight.core.module.IFloodlightModule; +import org.projectfloodlight.core.module.IFloodlightService; + +public class MockDebugCounterService implements IFloodlightModule, IDebugCounterService { + + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleServices() { + Collection<Class<? extends IFloodlightService>> services = + new ArrayList<Class<? extends IFloodlightService>>(1); + services.add(IDebugCounterService.class); + return services; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, + IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, + IFloodlightService>(); + m.put(IDebugCounterService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + return null; + } + + @Override + public void init(FloodlightModuleContext context) + throws FloodlightModuleException { + + } + + @Override + public void startUp(FloodlightModuleContext context) { + + } + + @Override + public boolean registerModule(String moduleName) { + return true; + } + + @Override + public IDebugCounter registerCounter(String moduleName, + String counterHierarchy, + String counterDescription, + MetaData... metaData) { + return new MockCounterImpl(); + } + + @Override + public boolean + resetCounterHierarchy(String moduleName, String counterHierarchy) { + return true; + } + + @Override + public void resetAllCounters() { + } + + @Override + public boolean resetAllModuleCounters(String moduleName) { + return true; + } + + @Override + public List<DebugCounterResource> + getCounterHierarchy(String moduleName, String counterHierarchy) { + return Collections.emptyList(); + } + + @Override + public List<DebugCounterResource> getAllCounterValues() { + return Collections.emptyList(); + } + + @Override + public List<DebugCounterResource> + getModuleCounterValues(String moduleName) { + return Collections.emptyList(); + } + + public static class MockCounterImpl implements IDebugCounter { + @Override + public void increment() { + } + + @Override + public void add(long incr) { + } + + @Override + public long getCounterValue() { + return -1; + } + } + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java deleted file mode 100644 index 5dc7b319219de1acb202ffdf3df1b347127bb10c..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java +++ /dev/null @@ -1,162 +0,0 @@ -package net.floodlightcontroller.debugcounter; - -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 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.debugcounter.DebugCounter.DebugCounterInfo; - -public class NullDebugCounter implements IFloodlightModule, IDebugCounterService { - - - @Override - public Collection<Class<? extends IFloodlightService>> - getModuleServices() { - Collection<Class<? extends IFloodlightService>> services = - new ArrayList<Class<? extends IFloodlightService>>(1); - services.add(IDebugCounterService.class); - return services; - } - - @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> - getServiceImpls() { - Map<Class<? extends IFloodlightService>, - IFloodlightService> m = - new HashMap<Class<? extends IFloodlightService>, - IFloodlightService>(); - m.put(IDebugCounterService.class, this); - return m; - } - - @Override - public Collection<Class<? extends IFloodlightService>> - getModuleDependencies() { - return null; - } - - @Override - public void init(FloodlightModuleContext context) - throws FloodlightModuleException { - - } - - @Override - public void startUp(FloodlightModuleContext context) { - - } - - - @Override - public void flushCounters() { - - } - - @Override - public void resetAllCounters() { - - } - - @Override - public void resetAllModuleCounters(String moduleName) { - - } - - - @Override - public void resetCounterHierarchy(String moduleName, String counterHierarchy) { - - } - - @Override - public void enableCtrOnDemand(String moduleName, String counterHierarchy) { - - } - - @Override - public void disableCtrOnDemand(String moduleName, String counterHierarchy) { - - } - - @Override - public List<DebugCounterInfo> getCounterHierarchy(String moduleName, - String counterHierarchy) { - return Collections.emptyList(); - } - - @Override - public List<DebugCounterInfo> getAllCounterValues() { - return Collections.emptyList(); - } - - @Override - public List<DebugCounterInfo> getModuleCounterValues(String moduleName) { - return Collections.emptyList(); - } - - @Override - public boolean containsModuleCounterHierarchy(String moduleName, - String counterHierarchy) { - return false; - } - - @Override - public boolean containsModuleName(String moduleName) { - return false; - } - - @Override - public - IDebugCounter - registerCounter(String moduleName, String counterHierarchy, - String counterDescription, - CounterType counterType, String... metaData) - throws MaxCountersRegistered { - return new NullCounterImpl(); - } - - @Override - public List<String> getModuleList() { - return Collections.emptyList(); - } - - @Override - public List<String> getModuleCounterList(String moduleName) { - return Collections.emptyList(); - } - - public class NullCounterImpl implements IDebugCounter { - - @Override - public void updateCounterWithFlush() { - - } - - @Override - public void updateCounterNoFlush() { - - } - - @Override - public void updateCounterWithFlush(int incr) { - } - - @Override - public void updateCounterNoFlush(int incr) { - - } - - @Override - public long getCounterValue() { - return -1; - } - - } -} diff --git a/src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java b/src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java new file mode 100644 index 0000000000000000000000000000000000000000..7e71d5490faacbd4710d4d9b8411fedc9bc5c9eb --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java @@ -0,0 +1,207 @@ +package net.floodlightcontroller.debugevent; + +import java.util.List; + +import javax.annotation.concurrent.Immutable; + +import org.projectfloodlight.db.data.annotation.DBProperty; +import org.projectfloodlight.debugevent.DebugEventService.EventInfo; +import org.projectfloodlight.debugevent.IDebugEventService.EventType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; + +/** + * All the Immutable Resource classes for REST API. + */ +@Immutable +public class DebugEventResource { + + protected static final Logger logger = LoggerFactory.getLogger(DebugEventResource.class); + public static final String MODULE_NAME_PREDICATE = "module-name"; + public static final String EVENT_NAME_PREDICATE = "event-name"; + public static final String LAST_PREDICATE = "num-of-events"; + public static final String EVENT_ID = "event-id"; + public static final String EVENT_INSTANCE_ID = "event-instance-id"; + public static final String ACKED = "acked"; + + /** + * Resource class for {@link EventInfo}. Used to create Immutable objects + * returned in response to REST calls. + */ + @Immutable + public static class EventInfoResource implements + Comparable<EventInfoResource> { + + private final int eventId; + private final boolean enabled; + private final int bufferCapacity; + private final EventType etype; + private final String eventDesc; + private final String eventName; + private final String moduleName; + private final int numOfEvents; + private final boolean ackable; + public final ImmutableList<EventResource> events; + + public EventInfoResource(EventInfo eventInfo, + List<EventResource> events) { + super(); + this.eventId = eventInfo.getEventId(); + this.enabled = eventInfo.isEnabled(); + this.bufferCapacity = eventInfo.getBufferCapacity(); + this.etype = eventInfo.getEtype(); + this.eventDesc = eventInfo.getEventDesc(); + this.eventName = eventInfo.getEventName(); + this.moduleName = eventInfo.getModuleName(); + this.numOfEvents = eventInfo.getNumOfEvents(); + this.ackable = eventInfo.isAckable(); + this.events = ImmutableList.copyOf(events); + } + + @DBProperty(value = "enabled") + public boolean isEnabled() { + return enabled; + } + + @DBProperty(value = "buffer-capacity") + public int getBufferCapacity() { + return bufferCapacity; + } + + @DBProperty(value = "etype") + public EventType getEtype() { + return etype; + } + + @DBProperty(value = "event-desc") + public String getEventDesc() { + return eventDesc; + } + + @DBProperty(value = "event-name") + public String getEventName() { + return eventName; + } + + @DBProperty(value = "module-name") + public String getModuleName() { + return moduleName; + } + + @DBProperty(value = "num-of-events") + public int getNumOfEvents() { + return numOfEvents; + } + + @DBProperty(value = "ackable") + public boolean isAckable() { + return ackable; + } + + @DBProperty(value = "event") + public List<EventResource> getEvents() { + return events; + } + + @DBProperty(value = "event-id") + public int getEventId() { + return eventId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (ackable ? 1231 : 1237); + result = prime * result + bufferCapacity; + result = prime * result + (enabled ? 1231 : 1237); + result = prime * result + + ((etype == null) ? 0 : etype.hashCode()); + result = prime * result + + ((eventDesc == null) ? 0 : eventDesc.hashCode()); + result = prime * result + eventId; + result = prime * result + + ((eventName == null) ? 0 : eventName.hashCode()); + result = prime * result + + ((events == null) ? 0 : events.hashCode()); + result = prime * result + + ((moduleName == null) ? 0 : moduleName.hashCode()); + result = prime * result + numOfEvents; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + EventInfoResource other = (EventInfoResource) obj; + if (ackable != other.ackable) return false; + if (bufferCapacity != other.bufferCapacity) return false; + if (enabled != other.enabled) return false; + if (etype != other.etype) return false; + if (eventDesc == null) { + if (other.eventDesc != null) return false; + } else if (!eventDesc.equals(other.eventDesc)) return false; + if (eventId != other.eventId) return false; + if (eventName == null) { + if (other.eventName != null) return false; + } else if (!eventName.equals(other.eventName)) return false; + if (events == null) { + if (other.events != null) return false; + } else if (!events.equals(other.events)) return false; + if (moduleName == null) { + if (other.moduleName != null) return false; + } else if (!moduleName.equals(other.moduleName)) return false; + if (numOfEvents != other.numOfEvents) return false; + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("EventInfoResource [eventId="); + builder.append(eventId); + builder.append(", enabled="); + builder.append(enabled); + builder.append(", bufferCapacity="); + builder.append(bufferCapacity); + builder.append(", etype="); + builder.append(etype); + builder.append(", eventDesc="); + builder.append(eventDesc); + builder.append(", eventName="); + builder.append(eventName); + builder.append(", moduleName="); + builder.append(moduleName); + builder.append(", numOfEvents="); + builder.append(numOfEvents); + builder.append(", ackable="); + builder.append(ackable); + builder.append(", events="); + builder.append(events); + builder.append("]"); + return builder.toString(); + } + + /** + * The natural order of this class is ascending on eventId and + * consistent with equals. + */ + @Override + public int compareTo(EventInfoResource o) { + return ComparisonChain.start().compare(eventId, o.eventId) + .compareFalseFirst(enabled, o.enabled) + .compare(bufferCapacity, o.bufferCapacity) + .compare(etype, o.etype) + .compare(eventDesc, o.eventDesc) + .compare(eventName, o.eventName) + .compare(moduleName, o.moduleName) + .compare(numOfEvents, o.numOfEvents) + .result(); + } + } +} diff --git a/src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java new file mode 100644 index 0000000000000000000000000000000000000000..113a42002ffdd43a35c903a029024e599d302bf4 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java @@ -0,0 +1,711 @@ +package net.floodlightcontroller.debugevent; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.projectfloodlight.core.IShutdownListener; +import org.projectfloodlight.core.IShutdownService; +import org.projectfloodlight.core.module.FloodlightModuleContext; +import org.projectfloodlight.core.module.IFloodlightModule; +import org.projectfloodlight.core.module.IFloodlightService; +import org.projectfloodlight.debugevent.DebugEventResource.EventInfoResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; + +/** + * This class implements a central store for all events used for debugging the + * system. The basic idea is that given the functionality provided by this + * class, it should be unnecessary to resort to scraping through system + * DEBUG/TRACE logs to understand behavior in a running system. + * + * @author Saurav + */ +public class DebugEventService implements IFloodlightModule, IDebugEventService { + protected static final Logger log = LoggerFactory.getLogger(DebugEventService.class); + + /** + * Every registered event type gets an event id AtomicInt to make the get + * operation thread-safe + */ + private final AtomicInteger eventIdCounter = new AtomicInteger(); + + /** + * Unique Event Instance Id for ack-ing + */ + private final AtomicLong eventInstanceId = new AtomicLong(Long.MAX_VALUE); + + private static final int PCT_LOCAL_CAP = 10; // % of global capacity + private static final int MIN_LOCAL_CAPACITY = 10; // elements + + /** + * EnumMap from {@link EventFieldType} to {@link CustomFormatter} + */ + static final ImmutableMap<EventFieldType, CustomFormatter<?>> customFormatter = + new ImmutableMap.Builder<EventFieldType, CustomFormatter<?>>() + .put(EventFieldType.DPID, new CustomFormatterDpid()) + .put(EventFieldType.IPv4, new CustomFormatterIpv4()) + .put(EventFieldType.MAC, new CustomFormatterMac()) + .put(EventFieldType.STRING, new CustomFormatterString()) + .put(EventFieldType.OBJECT, new CustomFormatterObject()) + .put(EventFieldType.PRIMITIVE, new CustomFormatterPrimitive()) + .put(EventFieldType.COLLECTION_IPV4, new CustomFormatterCollectionIpv4()) + .put(EventFieldType.COLLECTION_ATTACHMENT_POINT, new CustomFormatterCollectionAttachmentPoint()) + .put(EventFieldType.COLLECTION_OBJECT, new CustomFormatterCollectionObject()) + .put(EventFieldType.SREF_COLLECTION_OBJECT, new CustomFormatterSrefCollectionObject()) + .put(EventFieldType.SREF_OBJECT, new CustomFormatterSrefObject()) + .build(); + + /** + * Event Information + */ + public static class EventInfo { + private final int eventId; + private final boolean enabled; + private final int bufferCapacity; + private int numOfEvents; + private final EventType etype; + private final String eventDesc; + private final String eventName; + private final String moduleName; + private final String moduleEventName; + private final Class<?> eventClass; + private final boolean ackable; + + public EventInfo(int eventId, boolean enabled, boolean ackable, + int bufferCapacity, EventType etype, + Class<?> eventClass, String eventDesc, + String eventName, String moduleName) { + this.enabled = enabled; + this.ackable = ackable; + this.eventId = eventId; + this.bufferCapacity = bufferCapacity; + this.numOfEvents = bufferCapacity; + this.etype = etype; + this.eventClass = eventClass; + this.eventDesc = eventDesc; + this.eventName = eventName; + this.moduleName = moduleName; + this.moduleEventName = moduleName + "/" + eventName; + } + + public int getEventId() { + return eventId; + } + + public boolean isEnabled() { + return enabled; + } + + public boolean isAckable() { + return ackable; + } + + public int getBufferCapacity() { + return bufferCapacity; + } + + public int getNumOfEvents() { + return numOfEvents; + } + + public EventType getEtype() { + return etype; + } + + public String getEventDesc() { + return eventDesc; + } + + public String getEventName() { + return eventName; + } + + public String getModuleName() { + return moduleName; + } + + public String getModuleEventName() { + return moduleEventName; + } + } + + // ****************** + // Global stores + // ****************** + + /** + * Event history for a particular event-id is stored in a circular buffer + */ + protected static class DebugEventHistory { + EventInfo einfo; + LinkedBlockingDeque<Event> circularEventBuffer; + + public DebugEventHistory(EventInfo einfo, int capacity) { + this.einfo = einfo; + this.circularEventBuffer = new LinkedBlockingDeque<Event>( + capacity); + } + } + + /** + * Global storage for all event types and their corresponding event buffers. + * A particular event type is accessed by directly indexing into the Map + * with the corresponding event-id. <br/> + * It is a <b>Map</b> with <br/> + * <b>Key</b> Integer eventId <br/> + * <b>Value</b> DebugEventHistory + */ + protected final ConcurrentHashMap<Integer, DebugEventHistory> allEvents = new ConcurrentHashMap<Integer, DebugEventHistory>(); + + /** + * Global storage for all event ids registered for a module. The map is + * indexed by the module name and event name and returns the event-ids that + * correspond to the event types registered by that module (for example + * module 'linkdiscovery' may register events that have ids 0 and 1 that + * correspond to link up/down events, and receiving malformed LLDP packets, + * respectively). + */ + protected final ConcurrentHashMap<String, ConcurrentHashMap<String, Integer>> moduleEvents = new ConcurrentHashMap<String, ConcurrentHashMap<String, Integer>>(); + + /** + * A collection of event ids that are currently enabled for logging + */ + protected final Set<Integer> currentEvents = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>()); + + // ****************** + // Thread local stores + // ****************** + + /** + * Thread local storage for events + */ + protected static class LocalEventHistory { + private boolean enabled; + private final int capacity; + private ArrayList<Event> eventList; + + public LocalEventHistory(boolean enabled, int maxCapacity) { + this.enabled = enabled; + this.eventList = new ArrayList<Event>(maxCapacity); + this.capacity = maxCapacity; + } + + public boolean add(Event e) { + if (this.eventList.size() < capacity) { + this.eventList.add(e); + return true; + } + return false; + } + + public int drainTo(List<Event> eventList) { + int size = this.eventList.size(); + Iterator<Event> iter = this.eventList.iterator(); + while (iter.hasNext()) { + eventList.add(iter.next()); + } + this.eventList.clear(); + return size; + } + + public boolean isFull() { + if (eventList.size() == capacity) return true; + return false; + } + + public boolean isEmpty() { + return this.eventList.isEmpty(); + } + } + + /** + * Thread local event buffers used for maintaining event history local to a + * thread. Eventually this locally maintained information is flushed into + * the global event buffers. <br/> + * It is a <b>Map</b> with <br/> + * <b>Key</b> Integer eventId <br/> + * <b>Value</b> LocalEventHistory + */ + protected final ThreadLocal<Map<Integer, LocalEventHistory>> threadlocalEvents = new ThreadLocal<Map<Integer, LocalEventHistory>>() { + @Override + protected Map<Integer, LocalEventHistory> initialValue() { + return new HashMap<Integer, LocalEventHistory>(); + } + }; + + /** + * Thread local cache for event-ids that are currently active. + */ + protected final ThreadLocal<Set<Integer>> threadlocalCurrentEvents = new ThreadLocal<Set<Integer>>() { + @Override + protected Set<Integer> initialValue() { + return new HashSet<Integer>(); + } + }; + + // ******************************* + // IEventCategory + // ******************************* + + protected class EventCategory<T> implements IEventCategory<T> { + private final int eventId; + + public EventCategory(int evId) { + this.eventId = evId; + } + + @Override + public void newEventNoFlush(Object event) { + if (!validEventId()) return; + newEvent(eventId, false, event); + } + + @Override + public void newEventWithFlush(Object event) { + if (!validEventId()) return; + newEvent(eventId, true, event); + } + + private boolean validEventId() { + if (eventId < 0) { + throw new IllegalStateException(); + } + return true; + } + } + + public class EventCategoryBuilder<T> { + private int eventId; + private String moduleName; + private String eventName; + private String eventDescription; + private EventType eventType; + private Class<T> eventClass; + private int bufferCapacity; + private boolean ackable; + + public EventCategoryBuilder(Class<T> evClass) { + this.eventId = eventIdCounter.incrementAndGet(); + this.eventClass = evClass; + } + + public EventCategoryBuilder<T> setModuleName(String moduleName) { + this.moduleName = moduleName; + return this; + } + + public EventCategoryBuilder<T> setEventName(String eventName) { + this.eventName = eventName; + return this; + } + + public EventCategoryBuilder<T> setEventDescription(String eventDescription) { + this.eventDescription = eventDescription; + return this; + } + + public EventCategoryBuilder<T> setEventType(EventType et) { + this.eventType = et; + return this; + } + + public EventCategoryBuilder<T> setBufferCapacity(int bufferCapacity) { + this.bufferCapacity = bufferCapacity; + return this; + } + + public EventCategoryBuilder<T> setAckable(boolean ackable) { + this.ackable = ackable; + return this; + } + + /** + * Build a new {@link EventCategory<T>} <br/> + * Requires the following parameters to be set before being called: + * + * @param moduleName + * module registering event eg. linkdiscovery, virtualrouting. + * @param eventName + * name given to event. + * @param eventDescription + * A descriptive string describing the event. + * @param eventType + * EventType for this event. On-demand events have to be + * explicitly enabled using other methods in this API + * @param eventClass + * A user defined class that annotates the fields with + * @EventColumn. This class specifies the fields/columns for this + * event. + * @param bufferCapacity + * Number of events to store for this event in a circular buffer. + * Older events will be discarded once the buffer is full. + * @param ackable + * is the event used as part of ackable-event framework boolean + * + * @return IEventCategory with <b>newEvent</b> method that can be used + * to create instances of event of the given eventClass + */ + public EventCategory<T> register() { + // register event id for moduleName + moduleEvents.putIfAbsent(moduleName, + new ConcurrentHashMap<String, Integer>()); + Integer eventExists = moduleEvents.get(moduleName) + .putIfAbsent(eventName, eventId); + if (eventExists != null) { + log.error("Duplicate event registration for moduleName {} eventName {}", + moduleName, eventName); + return new EventCategory<T>(eventExists); + } + + // create storage for event-type + boolean enabled = (eventType == EventType.ALWAYS_LOG) ? true : false; + EventInfo ei = new EventInfo(eventId, enabled, ackable, + bufferCapacity, eventType, eventClass, + eventDescription, eventName, moduleName); + allEvents.put(eventId, new DebugEventHistory(ei, bufferCapacity)); + if (enabled) { + currentEvents.add(eventId); + } + + return new EventCategory<T>(this.eventId); + } + } + + // ******************************* + // IDebugEventService + // ******************************* + + @Override + public <T> EventCategoryBuilder<T> buildEvent(Class<T> evClass) { + return new EventCategoryBuilder<T>(evClass); + } + + private void flushLocalToGlobal(int eventId, LocalEventHistory le) { + DebugEventHistory de = allEvents.get(eventId); + if (de.einfo.enabled) { + List<Event> transferEvents = new ArrayList<Event>(); + // drain local buffer to Collection + int size = le.drainTo(transferEvents); + // if global buffer doesn't have enough space, clear + // some space + int requiredSpace = size + - de.circularEventBuffer.remainingCapacity(); + if (requiredSpace > 0) { + for (int i = 0; i < requiredSpace; i++) { + de.circularEventBuffer.removeFirst(); + } + } + de.circularEventBuffer.addAll(transferEvents); + } else { + le.enabled = false; + this.threadlocalCurrentEvents.get().remove(eventId); + } + } + + private void newEvent(int eventId, boolean flushNow, Object eventData) { + if (eventId < 0) { + throw new IllegalStateException("Invalid eventId"); + } + + Map<Integer, LocalEventHistory> thishist = this.threadlocalEvents.get(); + if (!thishist.containsKey(eventId)) { + // seeing this event for the first time in this thread - create + // local + // store by consulting global store + if (allEvents.containsKey(eventId)) { + DebugEventHistory de = allEvents.get(eventId); + boolean enabled = de.einfo.enabled; + int localCapacity = de.einfo.bufferCapacity * PCT_LOCAL_CAP + / 100; + if (localCapacity < 10) localCapacity = MIN_LOCAL_CAPACITY; + thishist.put(eventId, new LocalEventHistory(enabled, + localCapacity)); + if (enabled) { + Set<Integer> thisset = this.threadlocalCurrentEvents.get(); + thisset.add(eventId); + } + } else { + log.error("updateEvent seen locally for event {} but no global" + + "storage exists for it yet .. not updating", + eventId); + return; + } + } + + // update local store if enabled locally for updating + LocalEventHistory le = thishist.get(eventId); + if (le.enabled) { + try { + le.add(new Event(System.currentTimeMillis(), + Thread.currentThread().getId(), + Thread.currentThread().getName(), + eventData, + /* + * the eventInstanceId is started in reverse + * order so BigDB gets the values in ascending + * order Initialization in startUp() + */ + eventInstanceId.decrementAndGet())); + + if (le.isFull() || flushNow) { + flushLocalToGlobal(eventId, le); + } + } catch (IllegalStateException ise) { + log.debug("Exception while adding event locally: " + + ise.getMessage()); + } + } + } + + @Override + public void flushEvents() { + Map<Integer, LocalEventHistory> thishist = this.threadlocalEvents.get(); + Set<Integer> thisset = this.threadlocalCurrentEvents.get(); + + for (int eventId : thisset) { + if (thishist.containsKey(eventId)) { + LocalEventHistory le = thishist.get(eventId); + if (!le.isEmpty()) { + flushLocalToGlobal(eventId, le); + } + } + } + + // sync thread local currently enabled set of eventIds with global set. + Sets.SetView<Integer> sv = Sets.difference(currentEvents, thisset); + for (int eventId : sv) { + if (thishist.containsKey(eventId)) { + thishist.get(eventId).enabled = true; + thisset.add(eventId); + } + } + + } + + @Override + public boolean containsModuleEventName(String moduleName, + String eventName) { + if (!moduleEvents.containsKey(moduleName)) return false; + if (moduleEvents.get(moduleName).containsKey(eventName)) + return true; + return false; + } + + @Override + public boolean containsModuleName(String moduleName) { + return moduleEvents.containsKey(moduleName); + } + + @Override + public List<EventInfoResource> getAllEventHistory() { + List<EventInfoResource> moduleEventList = new ArrayList<EventInfoResource>(); + for (Map<String, Integer> modev : moduleEvents.values()) { + for (int eventId : modev.values()) { + if (allEvents.containsKey(eventId)) { + DebugEventHistory de = allEvents.get(eventId); + + List<EventResource> eventData = new ArrayList<EventResource>(); + // take snapshot and iterate + Iterator<Event> iter = de.circularEventBuffer.descendingIterator(); + while (iter.hasNext()) { + Event e = iter.next(); + eventData.add(e.getFormattedEvent(de.einfo.eventClass, + de.einfo.moduleEventName)); + } + moduleEventList.add(new EventInfoResource(de.einfo, + eventData)); + } + } + } + traceLogDebugHistory(moduleEventList); + return moduleEventList; + } + + @Override + public List<EventInfoResource> getModuleEventHistory(String moduleName) { + if (!moduleEvents.containsKey(moduleName)) + return Collections.emptyList(); + List<EventInfoResource> moduleEventList = new ArrayList<EventInfoResource>(); + for (int eventId : moduleEvents.get(moduleName).values()) { + if (allEvents.containsKey(eventId)) { + DebugEventHistory de = allEvents.get(eventId); + + List<EventResource> eventData = new ArrayList<EventResource>(); + // take snapshot and iterate + Iterator<Event> iter = de.circularEventBuffer.descendingIterator(); + while (iter.hasNext()) { + Event e = iter.next(); + eventData.add(e.getFormattedEvent(de.einfo.eventClass, + de.einfo.moduleEventName)); + } + moduleEventList.add(new EventInfoResource(de.einfo, + eventData)); + } + } + traceLogDebugHistory(moduleEventList); + return moduleEventList; + } + + @Override + public EventInfoResource getSingleEventHistory(String moduleName, + String eventName, + int numOfEvents) { + if (!moduleEvents.containsKey(moduleName)) return null; + Integer eventId = moduleEvents.get(moduleName).get(eventName); + if (eventId == null) return null; + + if (!allEvents.containsKey(eventId)) return null; + + DebugEventHistory de = allEvents.get(eventId); + if (numOfEvents == 0) numOfEvents = de.einfo.bufferCapacity; + + de.einfo.numOfEvents = numOfEvents; + int num = 1; + List<EventResource> eventData = new ArrayList<EventResource>(); + // take snapshot and iterate + Iterator<Event> iter = de.circularEventBuffer.descendingIterator(); + while (iter.hasNext()) { + Event e = iter.next(); + if (num > numOfEvents) break; + eventData.add(e.getFormattedEvent(de.einfo.eventClass, + de.einfo.moduleEventName)); + num++; + } + EventInfoResource ret = new EventInfoResource(de.einfo, eventData); + traceLogDebugHistory(Collections.singletonList(ret)); + return ret; + } + + @Override + public void resetAllEvents() { + for (Map<String, Integer> eventMap : moduleEvents.values()) { + for (Integer evId : eventMap.values()) { + allEvents.get(evId).circularEventBuffer.clear(); + } + } + } + + @Override + public void resetAllModuleEvents(String moduleName) { + if (!moduleEvents.containsKey(moduleName)) return; + Map<String, Integer> modEvents = moduleEvents.get(moduleName); + for (Integer evId : modEvents.values()) { + allEvents.get(evId).circularEventBuffer.clear(); + } + } + + @Override + public void resetSingleEvent(String moduleName, String eventName) { + if (!moduleEvents.containsKey(moduleName)) return; + Integer eventId = moduleEvents.get(moduleName).get(eventName); + if (eventId == null) return; + + if (allEvents.containsKey(eventId)) { + allEvents.get(eventId).circularEventBuffer.clear(); + } + } + + @Override + public void setAck(int eventId, long eventInstanceId, boolean ack) { + if (allEvents.containsKey(eventId)) { + for (Event e : allEvents.get(eventId).circularEventBuffer) { + if (e.getEventInstanceId() == eventInstanceId) { + e.setAcked(ack); + } + } + } + } + + @Override + public List<String> getModuleList() { + List<String> el = new ArrayList<String>(); + el.addAll(moduleEvents.keySet()); + return el; + } + + @Override + public List<String> getModuleEventList(String moduleName) { + if (!moduleEvents.containsKey(moduleName)) + return Collections.emptyList(); + List<String> el = new ArrayList<String>(); + el.addAll(moduleEvents.get(moduleName).keySet()); + return el; + } + + + private void traceLogDebugHistory(List<EventInfoResource> l) { + if (!log.isTraceEnabled()) { + return; + } + for (EventInfoResource eir: l) { + for (EventResource der: eir.getEvents()) { + log.trace("{}", der); + } + } + } + + private class ShutdownListenenerDelegate implements IShutdownListener { + @Override + public void floodlightIsShuttingDown() { + for (EventInfoResource eir: getAllEventHistory()) { + for (EventResource der: eir.getEvents()) { + log.info("{}", der); + } + } + } + } + + // ******************************* + // IFloodlightModule + // ******************************* + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IDebugEventService.class); + return l; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); + m.put(IDebugEventService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + ArrayList<Class<? extends IFloodlightService>> deps = new ArrayList<Class<? extends IFloodlightService>>(); + deps.add(IShutdownService.class); + return deps; + } + + @Override + public void init(FloodlightModuleContext context) { + } + + @Override + public void startUp(FloodlightModuleContext context) { + IShutdownService shutdownService = + context.getServiceImpl(IShutdownService.class); + shutdownService.registerShutdownListener(new ShutdownListenenerDelegate()); + DebugEventAppender.setDebugEventServiceImpl(this); + } +} diff --git a/src/main/java/net/floodlightcontroller/debugevent/Event.java b/src/main/java/net/floodlightcontroller/debugevent/Event.java index 3e0ac6db32eba864cb27c335553ade8a1bf5cfc6..1eb76a1a80b0b1227e1867d27f2bb07849358ae7 100644 --- a/src/main/java/net/floodlightcontroller/debugevent/Event.java +++ b/src/main/java/net/floodlightcontroller/debugevent/Event.java @@ -11,8 +11,10 @@ import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; import net.floodlightcontroller.devicemanager.SwitchPort; import net.floodlightcontroller.packet.IPv4; -import org.openflow.protocol.OFFlowMod; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.OFFlowModFlags; +import org.projectfloodlight.openflow.protocol.OFFlowModify; +import org.projectfloodlight.openflow.util.HexString; public class Event { long timestamp; @@ -110,8 +112,8 @@ public class Event { if (flags == 0) { builder.append("None"); } - else { - if ((flags & OFFlowMod.OFPFF_SEND_FLOW_REM) != 0) { + else { //towirevalue + if ((flags & OFFlowModFlags.SEND_FLOW_REM.) != 0) { builder.append("SEND_FLOW_REM "); } if ((flags & OFFlowMod.OFPFF_CHECK_OVERLAP) != 0) { diff --git a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java deleted file mode 100644 index d54e9f632af539f53ecdd9e4b2b4477cba8d79d5..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java +++ /dev/null @@ -1,189 +0,0 @@ -package net.floodlightcontroller.debugevent; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.List; -import java.util.Map; - -import net.floodlightcontroller.core.module.IFloodlightService; -import net.floodlightcontroller.debugevent.DebugEvent.EventInfo; - -public interface IDebugEventService extends IFloodlightService { - - /** - * Different event types. Events that are meant to be logged on demand - * need to be separately enabled/disabled. - */ - public enum EventType { - ALWAYS_LOG, - LOG_ON_DEMAND - } - - /** - * Describes the type of field obtained from reflection - */ - enum EventFieldType { - DPID, IPv4, MAC, STRING, OBJECT, PRIMITIVE, LIST_IPV4, - LIST_ATTACHMENT_POINT, LIST_OBJECT, SREF_LIST_OBJECT, SREF_OBJECT, - FLOW_MOD_FLAGS - } - - /** - * EventColumn is the only annotation given to the fields of the event - * when updating an event. - */ - @Target(ElementType.FIELD) - @Retention(RetentionPolicy.RUNTIME) - public @interface EventColumn { - String name() default "param"; - EventFieldType description() default EventFieldType.PRIMITIVE; - } - - /** - * Debug Event Qualifiers - */ - public static final String EV_MDATA_WARN = "warn"; - public static final String EV_MDATA_ERROR = "error"; - - /** - * A limit on the maximum number of events that can be created - */ - public static final int MAX_EVENTS = 2000; - - /** - * Public class for information returned in response to rest API calls. - */ - public class DebugEventInfo { - EventInfo eventInfo; - List<Map<String,String>> events; - - public DebugEventInfo(EventInfo eventInfo, - List<Map<String, String>> eventHistory) { - this.eventInfo = eventInfo; - this.events = eventHistory; - } - - public EventInfo getEventInfo() { - return eventInfo; - } - - public List<Map<String,String>> getEvents() { - return events; - } - } - - /** - * exception thrown when MAX_EVENTS have been registered - */ - public class MaxEventsRegistered extends Exception { - private static final long serialVersionUID = 2609587082227510262L; - } - - /** - * Register an event for debugging. - * - * @param moduleName module registering event eg. linkdiscovery, virtualrouting. - * @param eventName name given to event. - * @param eventDescription A descriptive string describing the event. - * @param eventType EventType for this event. On-demand events have to - * be explicitly enabled using other methods in this API - * @param eventClass A user defined class that annotates the fields - * with @EventColumn. This class specifies the - * fields/columns for this event. - * @param bufferCapacity Number of events to store for this event in a circular - * buffer. Older events will be discarded once the - * buffer is full. - * @param metaData variable arguments that qualify an event - * eg. EV_MDATA_WARN, EV_MDATA_ERROR etc. See Debug Event Qualifiers - * @return IEventUpdater with update methods that can be used to - * update an event of the given eventClass - * @throws MaxEventsRegistered - */ - public <T> IEventUpdater<T> registerEvent(String moduleName, String eventName, - String eventDescription, - EventType eventType, - Class<T> eventClass, - int bufferCapacity, - String... metaData) - throws MaxEventsRegistered; - - /** - * Update the global event stores with values from the thread local stores. This - * method is not typically intended for use by any module. It's typical usage is from - * floodlight core for events that happen in the packet processing pipeline. - * For other rare events, flushEvents should be called. - */ - public void flushEvents(); - - /** - * Determine if eventName is a registered event for a given moduleName - */ - public boolean containsModuleEventName(String moduleName, String eventName); - - /** - * Determine if any events have been registered for module of name moduleName - */ - public boolean containsModuleName(String moduleName); - - /** - * Get event history for all events. This call can be expensive as it - * formats the event histories for all events. - * - * @return a list of all event histories or an empty list if no events have - * been registered - */ - public List<DebugEventInfo> getAllEventHistory(); - - /** - * Get event history for all events registered for a given moduleName - * - * @return a list of all event histories for all events registered for the - * the module or an empty list if there are no events for this module - */ - public List<DebugEventInfo> getModuleEventHistory(String moduleName); - - /** - * Get event history for a single event - * - * @param moduleName registered module name - * @param eventName registered event name for moduleName - * @param last last X events - * @return DebugEventInfo for that event, or null if the moduleEventName - * does not correspond to a registered event. - */ - public DebugEventInfo getSingleEventHistory(String moduleName, String eventName, int last); - - /** - * Wipe out all event history for all registered events - */ - public void resetAllEvents(); - - /** - * Wipe out all event history for all events registered for a specific module - * - * @param moduleName registered module name - */ - public void resetAllModuleEvents(String moduleName); - - /** - * Wipe out event history for a single event - * @param moduleName registered module name - * @param eventName registered event name for moduleName - */ - public void resetSingleEvent(String moduleName, String eventName); - - /** - * Retrieve a list of moduleNames registered for debug events or an empty - * list if no events have been registered in the system - */ - public List<String> getModuleList(); - - /** - * Returns a list of all events registered for a specific moduleName - * or a empty list - */ - public List<String> getModuleEventList(String moduleName); - -} diff --git a/src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java b/src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java new file mode 100644 index 0000000000000000000000000000000000000000..00cea123269b5aadef0d5438889ffaf00b24c2fb --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java @@ -0,0 +1,30 @@ +package net.floodlightcontroller.debugevent; + +/** + * EventCategory is used to log events for pre-registered events. + */ +public interface IEventCategory<T> { + + /** + * Logs the instance of the event thread-locally. Flushing to the global + * circular buffer for this event is delayed resulting in better + * performance. This method should typically be used by those events that + * happen in the packet processing pipeline + * + * @param event + * an instance of the user-defined event of type T + */ + public void newEventNoFlush(T event); + + /** + * Logs the instance of the event thread-locally and immediated flushes to + * the global circular buffer for this event. This method should typically + * be used by those events that happen outside the packet processing + * pipeline + * + * @param event + * an instance of the user-defined event of type T + */ + public void newEventWithFlush(T event); + +} diff --git a/src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java new file mode 100644 index 0000000000000000000000000000000000000000..7f0676a556f37be26f259dfd883e8191c932b5a6 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java @@ -0,0 +1,128 @@ +package net.floodlightcontroller.debugevent; + +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 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.debugevent.DebugEventResource.EventInfoResource; +import net.floodlightcontroller.debugevent.DebugEventService.EventCategoryBuilder; + +public class MockDebugEventService implements IFloodlightModule, IDebugEventService { + + @Override + public <T> EventCategoryBuilder<T> buildEvent(Class<T> evClass) { + DebugEventService des = new DebugEventService(); + return des.buildEvent(evClass); + } + + @Override + public void flushEvents() { + + } + + @Override + public boolean containsModuleEventName(String moduleName, + String eventName) { + return false; + } + + @Override + public boolean containsModuleName(String moduleName) { + return false; + } + + @Override + public List<EventInfoResource> getAllEventHistory() { + return Collections.emptyList(); + } + + @Override + public List<EventInfoResource> getModuleEventHistory(String moduleName) { + return Collections.emptyList(); + } + + @Override + public EventInfoResource getSingleEventHistory(String moduleName, + String eventName, + int numOfEvents) { + return null; + } + + @Override + public void resetAllEvents() { + + } + + @Override + public void resetAllModuleEvents(String moduleName) { + + } + + @Override + public void resetSingleEvent(String moduleName, String eventName) { + + } + + @Override + public List<String> getModuleList() { + return Collections.emptyList(); + } + + @Override + public List<String> getModuleEventList(String moduleName) { + return Collections.emptyList(); + } + + @Override + public void setAck(int eventId, long eventInstanceId, boolean ack) { + + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleServices() { + Collection<Class<? extends IFloodlightService>> services = + new ArrayList<Class<? extends IFloodlightService>>(1); + services.add(IDebugEventService.class); + return services; + } + + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> + getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); + m.put(IDebugEventService.class, this); + return m; + } + + @Override + public Collection<Class<? extends IFloodlightService>> + getModuleDependencies() { + return null; + } + + @Override + public + void + init(FloodlightModuleContext context) + throws FloodlightModuleException { + + } + + @Override + public + void + startUp(FloodlightModuleContext context) + throws FloodlightModuleException { + + } + +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java b/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java index 4593b7bac9d8f4b25f9a3c1e5c4693bfd1a0fca0..4d5ba9be6d5d5ef7f31a4316cb92d2303a62502f 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java @@ -19,6 +19,10 @@ package net.floodlightcontroller.devicemanager; import java.util.Date; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.VlanVid; + /** * Represents an independent device on the network. A device consists of a @@ -37,7 +41,7 @@ public interface IDevice { * Get the MAC address of the device as a Long value. * @return the MAC address for the device */ - public long getMACAddress(); + public MacAddress getMACAddress(); /** * Get the MAC address of the device as a String value. @@ -50,13 +54,13 @@ public interface IDevice { * entities, then the value -1 will be returned. * @return an array containing all unique VLAN IDs for the device. */ - public Short[] getVlanId(); + public VlanVid[] getVlanId(); /** * Get all unique IPv4 addresses associated with the device. * @return an array containing the unique IPv4 addresses for the device. */ - public Integer[] getIPv4Addresses(); + public IPv4Address[] getIPv4Addresses(); /** * Get all unique attachment points associated with the device. This will @@ -85,7 +89,7 @@ public interface IDevice { * @param swp the switch port to query * @return an array containing the unique VLAN IDs */ - public Short[] getSwitchPortVlanIds(SwitchPort swp); + public VlanVid[] getSwitchPortVlanIds(SwitchPort swp); /** * Get the most recent timestamp for this device diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java index eb3801344f73d68ab0c35e6db556c09edfa1ba68..40d729f6894149d9a1e3142c618bc606c0753a4b 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java @@ -22,6 +22,12 @@ import java.util.EnumSet; import java.util.Iterator; import java.util.Set; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.VlanVid; +import org.projectfloodlight.openflow.types.OFPort; + import net.floodlightcontroller.core.FloodlightContextStore; import net.floodlightcontroller.core.module.IFloodlightService; @@ -95,9 +101,9 @@ public interface IDeviceService extends IFloodlightService { * @throws IllegalArgumentException if not all key fields of the * current {@link IEntityClassifierService} are specified. */ - public IDevice findDevice(long macAddress, Short vlan, - Integer ipv4Address, Long switchDPID, - Integer switchPort) + public IDevice findDevice(MacAddress macAddress, VlanVid vlan, + IPv4Address ipv4Address, DatapathId switchDPID, + OFPort switchPort) throws IllegalArgumentException; /** @@ -122,8 +128,8 @@ public interface IDeviceService extends IFloodlightService { * source's {@link IEntityClass} are specified. */ public IDevice findClassDevice(IEntityClass entityClass, - long macAddress, Short vlan, - Integer ipv4Address) + MacAddress macAddress, VlanVid vlan, + IPv4Address ipv4Address) throws IllegalArgumentException; /** @@ -162,11 +168,11 @@ public interface IDeviceService extends IFloodlightService { * @see IDeviceService#queryClassDevices(IEntityClass, Long, * Short, Integer, Long, Integer) */ - public Iterator<? extends IDevice> queryDevices(Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort); + public Iterator<? extends IDevice> queryDevices(MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort); /** * Find devices that match the provided query. Only the index for @@ -187,11 +193,11 @@ public interface IDeviceService extends IFloodlightService { * Short, Integer, Long, Integer) */ public Iterator<? extends IDevice> queryClassDevices(IEntityClass entityClass, - Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort); + MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort); /** * Adds a listener to listen for IDeviceManagerServices notifications @@ -207,9 +213,9 @@ public interface IDeviceService extends IFloodlightService { * @param sw * @param port */ - public void addSuppressAPs(long swId, short port); + public void addSuppressAPs(DatapathId swId, OFPort port); - public void removeSuppressAPs(long swId, short port); + public void removeSuppressAPs(DatapathId swId, OFPort port); public Set<SwitchPort> getSuppressAPs(); diff --git a/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java b/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java index 9fe62d9507c0d2e575bebaa8bdcc86b8c15676a4..d057f9c4a353f0501631f6cf7725fd00d4be5b4e 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java @@ -17,7 +17,8 @@ package net.floodlightcontroller.devicemanager; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; import net.floodlightcontroller.core.web.serializers.DPIDSerializer; @@ -55,8 +56,8 @@ public class SwitchPort { } } - private final long switchDPID; - private final int port; + private final DatapathId switchDPID; + private final OFPort port; private final ErrorStatus errorStatus; /** @@ -65,7 +66,7 @@ public class SwitchPort { * @param port the port * @param errorStatus any error status for the switch port */ - public SwitchPort(long switchDPID, int port, ErrorStatus errorStatus) { + public SwitchPort(DatapathId switchDPID, OFPort port, ErrorStatus errorStatus) { super(); this.switchDPID = switchDPID; this.port = port; @@ -77,7 +78,7 @@ public class SwitchPort { * @param switchDPID the dpid * @param port the port */ - public SwitchPort(long switchDPID, int port) { + public SwitchPort(DatapathId switchDPID, OFPort port) { super(); this.switchDPID = switchDPID; this.port = port; @@ -89,11 +90,11 @@ public class SwitchPort { // *************** @JsonSerialize(using=DPIDSerializer.class) - public long getSwitchDPID() { + public DatapathId getSwitchDPID() { return switchDPID; } - public int getPort() { + public OFPort getPort() { return port; } @@ -113,8 +114,8 @@ public class SwitchPort { + ((errorStatus == null) ? 0 : errorStatus.hashCode()); - result = prime * result + port; - result = prime * result + (int) (switchDPID ^ (switchDPID >>> 32)); + result = prime * result + port.getPortNumber(); + result = prime * result + (int) (switchDPID.getLong() ^ (switchDPID.getLong() >>> 32)); return result; } @@ -132,7 +133,7 @@ public class SwitchPort { @Override public String toString() { - return "SwitchPort [switchDPID=" + HexString.toHexString(switchDPID) + + return "SwitchPort [switchDPID=" + switchDPID.toString() + ", port=" + port + ", errorStatus=" + errorStatus + "]"; } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java index a08a3a5d2cb723582cf422b5ca988a22ac61e3f2..46c2408faef824cb4ccf74c9dd69515037f70f3a 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java @@ -21,11 +21,16 @@ package net.floodlightcontroller.devicemanager.internal; +import java.util.Date; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; + public class AttachmentPoint { - long sw; - short port; - long activeSince; - long lastSeen; + DatapathId sw; + OFPort port; + Date activeSince; + Date lastSeen; // Timeout for moving attachment points from OF/broadcast // domain to another. @@ -34,15 +39,15 @@ public class AttachmentPoint { public static final long OPENFLOW_TO_EXTERNAL_TIMEOUT = 30000; // 30 seconds public static final long CONSISTENT_TIMEOUT = 30000; // 30 seconds - public AttachmentPoint(long sw, short port, long activeSince, - long lastSeen) { + public AttachmentPoint(DatapathId sw, OFPort port, Date activeSince, + Date lastSeen) { this.sw = sw; this.port = port; this.activeSince = activeSince; this.lastSeen = lastSeen; } - public AttachmentPoint(long sw, short port, long lastSeen) { + public AttachmentPoint(DatapathId sw, OFPort port, Date lastSeen) { this.sw = sw; this.port = port; this.lastSeen = lastSeen; @@ -56,31 +61,31 @@ public class AttachmentPoint { this.lastSeen = ap.lastSeen; } - public long getSw() { + public DatapathId getSw() { return sw; } - public void setSw(long sw) { + public void setSw(DatapathId sw) { this.sw = sw; } - public short getPort() { + public OFPort getPort() { return port; } - public void setPort(short port) { + public void setPort(OFPort port) { this.port = port; } - public long getActiveSince() { + public Date getActiveSince() { return activeSince; } - public void setActiveSince(long activeSince) { + public void setActiveSince(Date activeSince) { this.activeSince = activeSince; } - public long getLastSeen() { + public Date getLastSeen() { return lastSeen; } - public void setLastSeen(long lastSeen) { - if (this.lastSeen + INACTIVITY_INTERVAL < lastSeen) + public void setLastSeen(Date lastSeen) { + if (this.lastSeen.getTime() + INACTIVITY_INTERVAL < lastSeen.getTime()) this.activeSince = lastSeen; - if (this.lastSeen < lastSeen) + if (this.lastSeen.before(lastSeen)) this.lastSeen = lastSeen; } @@ -91,8 +96,8 @@ public class AttachmentPoint { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + port; - result = prime * result + (int) (sw ^ (sw >>> 32)); + result = prime * result + port.getPortNumber(); + result = prime * result + (int) (sw.getLong() ^ (sw.getLong() >>> 32)); return result; } @@ -118,7 +123,7 @@ public class AttachmentPoint { @Override public String toString() { return "AttachmentPoint [sw=" + sw + ", port=" + port - + ", activeSince=" + activeSince + ", lastSeen=" + lastSeen + + ", activeSince=" + activeSince + ", lastSeen=" + lastSeen.toString() + "]"; } } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java index ef0ba346809496090c83e273be35c5576699369c..07e5b77bfbacf879ce6b749fe7cbe811d1c90f85 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java @@ -30,7 +30,11 @@ import java.util.Map; import java.util.TreeSet; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; +import org.projectfloodlight.openflow.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,7 +65,7 @@ public class Device implements IDevice { protected final String macAddressString; // the vlan Ids from the entities of this device - protected final Short[] vlanIds; + protected final VlanVid[] vlanIds; protected volatile String dhcpClientName; /** @@ -103,7 +107,7 @@ public class Device implements IDevice { if (entity.getSwitchDPID() != null && entity.getSwitchPort() != null){ - long sw = entity.getSwitchDPID(); + DatapathId sw = entity.getSwitchDPID(); short port = entity.getSwitchPort().shortValue(); if (deviceManager.isValidAttachmentPoint(sw, port)) { @@ -209,30 +213,29 @@ public class Device implements IDevice { new ArrayList<AttachmentPoint>(device.attachmentPoints); } - this.macAddressString = - HexString.toHexString(this.entities[0].getMacAddress(), 6); + this.macAddressString = this.entities[0].getMacAddress().toString(); this.entityClass = device.entityClass; vlanIds = computeVlandIds(); } - private Short[] computeVlandIds() { + private VlanVid[] computeVlandIds() { if (entities.length == 1) { if (entities[0].getVlan() != null) { - return new Short[]{ entities[0].getVlan() }; + return new VlanVid[]{ entities[0].getVlan() }; } else { - return new Short[] { Short.valueOf((short)-1) }; + return new VlanVid[] { VlanVid.ofVlan(-1) }; } } - TreeSet<Short> vals = new TreeSet<Short>(); + TreeSet<VlanVid> vals = new TreeSet<VlanVid>(); for (Entity e : entities) { if (e.getVlan() == null) - vals.add((short)-1); + vals.add(VlanVid.ofVlan(-1)); else vals.add(e.getVlan()); } - return vals.toArray(new Short[vals.size()]); + return vals.toArray(new VlanVid[vals.size()]); } /** @@ -293,7 +296,7 @@ public class Device implements IDevice { if (apList == null) return false; for(AttachmentPoint ap: apList) { - if (ap.getLastSeen() + AttachmentPoint.INACTIVITY_INTERVAL < + if (ap.getLastSeen().getTime() + AttachmentPoint.INACTIVITY_INTERVAL < System.currentTimeMillis()) expiredAPs.add(ap); } @@ -332,8 +335,8 @@ public class Device implements IDevice { if (trueAP == null) continue; boolean c = (topology.isConsistent(trueAP.getSw(), trueAP.getPort(), ap.getSw(), ap.getPort())); - boolean active = (ap.getActiveSince() > trueAP.getActiveSince()); - boolean last = ap.getLastSeen() > timeThreshold; + boolean active = (ap.getActiveSince().after(trueAP.getActiveSince())); + boolean last = ap.getLastSeen().getTime() > timeThreshold; if (!c && active && last) { dupAPs.add(ap); } @@ -385,7 +388,7 @@ public class Device implements IDevice { * @param lastSeen * @return */ - protected boolean updateAttachmentPoint(long sw, short port, long lastSeen){ + protected boolean updateAttachmentPoint(DatapathId sw, OFPort port, Date lastSeen){ ITopologyService topology = deviceManager.topology; List<AttachmentPoint> oldAPList; List<AttachmentPoint> apList; diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java index 2cbea66e5577495461171661f479c4f26335f11f..d9a7a4532284bc30bc74bd2f8017ecca854bee89 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java @@ -20,6 +20,12 @@ package net.floodlightcontroller.devicemanager.internal; import java.util.Arrays; import java.util.Iterator; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; + import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.devicemanager.SwitchPort; import net.floodlightcontroller.util.FilterIterator; @@ -30,11 +36,11 @@ import net.floodlightcontroller.util.FilterIterator; public class DeviceIterator extends FilterIterator<Device> { private IEntityClass[] entityClasses; - private Long macAddress; - private Short vlan; - private Integer ipv4Address; - private Long switchDPID; - private Integer switchPort; + private MacAddress macAddress; + private VlanVid vlan; + private IPv4Address ipv4Address; + private DatapathId switchDPID; + private OFPort switchPort; /** * Construct a new device iterator over the key fields @@ -48,11 +54,11 @@ public class DeviceIterator extends FilterIterator<Device> { */ public DeviceIterator(Iterator<Device> subIterator, IEntityClass[] entityClasses, - Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort) { + MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort) { super(subIterator); this.entityClasses = entityClasses; this.subIterator = subIterator; @@ -80,7 +86,7 @@ public class DeviceIterator extends FilterIterator<Device> { if (!match) return false; } if (macAddress != null) { - if (macAddress.longValue() != value.getMACAddress()) + if (macAddress.getLong() != value.getMACAddress()) return false; } if (vlan != null) { @@ -100,11 +106,11 @@ public class DeviceIterator extends FilterIterator<Device> { match = false; for (SwitchPort sp : sps) { if (switchDPID != null) { - if (switchDPID.longValue() != sp.getSwitchDPID()) + if (switchDPID.getLong() != sp.getSwitchDPID().getLong()) return false; } if (switchPort != null) { - if (switchPort.intValue() != sp.getPort()) + if (switchPort.getPortNumber() != sp.getPort().getPortNumber()) return false; } match = true; diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index e4f67420bed7489558a389dd6714c14b57451766..7d34fc3f6d789dfdd9bb1c3ecd42369ab85a1244 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -47,7 +47,7 @@ import net.floodlightcontroller.core.IHAListener; import net.floodlightcontroller.core.IInfoProvider; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.IFloodlightProviderService.Role; +import net.floodlightcontroller.core.HARole; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; @@ -96,11 +96,15 @@ import net.floodlightcontroller.util.MultiIterator; import static net.floodlightcontroller.devicemanager.internal. DeviceManagerImpl.DeviceUpdate.Change.*; -import org.openflow.protocol.OFMatchWithSwDpid; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFMatchWithSwDpid; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; +import org.projectfloodlight.openflow.protocol.OFType; import org.sdnplatform.sync.IClosableIterator; import org.sdnplatform.sync.IStoreClient; import org.sdnplatform.sync.ISyncService; @@ -360,33 +364,33 @@ IFlowReconcileListener, IInfoProvider { public int compare(AttachmentPoint oldAP, AttachmentPoint newAP) { //First compare based on L2 domain ID; - long oldSw = oldAP.getSw(); - short oldPort = oldAP.getPort(); - long oldDomain = topology.getL2DomainId(oldSw); + DatapathId oldSw = oldAP.getSw(); + OFPort oldPort = oldAP.getPort(); + DatapathId oldDomain = topology.getL2DomainId(oldSw); boolean oldBD = topology.isBroadcastDomainPort(oldSw, oldPort); - long newSw = newAP.getSw(); - short newPort = newAP.getPort(); - long newDomain = topology.getL2DomainId(newSw); + DatapathId newSw = newAP.getSw(); + OFPort newPort = newAP.getPort(); + DatapathId newDomain = topology.getL2DomainId(newSw); boolean newBD = topology.isBroadcastDomainPort(newSw, newPort); - if (oldDomain < newDomain) return -1; - else if (oldDomain > newDomain) return 1; + if (oldDomain.getLong() < newDomain.getLong()) return -1; + else if (oldDomain.getLong() > newDomain.getLong()) return 1; - // Give preference to OFPP_LOCAL always - if (oldPort != OFPort.OFPP_LOCAL.getValue() && - newPort == OFPort.OFPP_LOCAL.getValue()) { + // Give preference to LOCAL always + if (oldPort != OFPort.LOCAL && + newPort == OFPort.LOCAL) { return -1; - } else if (oldPort == OFPort.OFPP_LOCAL.getValue() && - newPort != OFPort.OFPP_LOCAL.getValue()) { + } else if (oldPort == OFPort.LOCAL && + newPort != OFPort.LOCAL) { return 1; } // We expect that the last seen of the new AP is higher than // old AP, if it is not, just reverse and send the negative // of the result. - if (oldAP.getActiveSince() > newAP.getActiveSince()) + if (oldAP.getActiveSince().after(newAP.getActiveSince())) return -compare(newAP, oldAP); long activeOffset = 0; @@ -407,8 +411,8 @@ IFlowReconcileListener, IInfoProvider { } - if ((newAP.getActiveSince() > oldAP.getLastSeen() + activeOffset) || - (newAP.getLastSeen() > oldAP.getLastSeen() + + if ((newAP.getActiveSince().getTime() > oldAP.getLastSeen().getTime() + activeOffset) || + (newAP.getLastSeen().getTime() > oldAP.getLastSeen().getTime() + AttachmentPoint.INACTIVITY_INTERVAL)) { return -1; } @@ -453,13 +457,13 @@ IFlowReconcileListener, IInfoProvider { } @Override - public IDevice findDevice(long macAddress, Short vlan, - Integer ipv4Address, Long switchDPID, - Integer switchPort) + public IDevice findDevice(MacAddress macAddress, VlanVid vlan, + IPv4Address ipv4Address, DatapathId switchDPID, + OFPort switchPort) throws IllegalArgumentException { - if (vlan != null && vlan.shortValue() <= 0) + if (vlan != null && vlan.getVlan() <= 0) vlan = null; - if (ipv4Address != null && ipv4Address == 0) + if (ipv4Address != null && ipv4Address.getInt() == 0) ipv4Address = null; Entity e = new Entity(macAddress, vlan, ipv4Address, switchDPID, switchPort, null); @@ -471,12 +475,12 @@ IFlowReconcileListener, IInfoProvider { } @Override - public IDevice findClassDevice(IEntityClass entityClass, long macAddress, - Short vlan, Integer ipv4Address) + public IDevice findClassDevice(IEntityClass entityClass, MacAddress macAddress, + VlanVid vlan, IPv4Address ipv4Address) throws IllegalArgumentException { - if (vlan != null && vlan.shortValue() <= 0) + if (vlan != null && vlan.getVlan() <= 0) vlan = null; - if (ipv4Address != null && ipv4Address == 0) + if (ipv4Address != null && ipv4Address.getInt() == 0) ipv4Address = null; Entity e = new Entity(macAddress, vlan, ipv4Address, null, null, null); @@ -506,11 +510,11 @@ IFlowReconcileListener, IInfoProvider { } @Override - public Iterator<? extends IDevice> queryDevices(Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort) { + public Iterator<? extends IDevice> queryDevices(MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort) { DeviceIndex index = null; if (secondaryIndexMap.size() > 0) { EnumSet<DeviceField> keys = @@ -525,7 +529,7 @@ IFlowReconcileListener, IInfoProvider { deviceIterator = deviceMap.values().iterator(); } else { // index lookup - Entity entity = new Entity((macAddress == null ? 0 : macAddress), + Entity entity = new Entity(macAddress, vlan, ipv4Address, switchDPID, @@ -548,11 +552,11 @@ IFlowReconcileListener, IInfoProvider { @Override public Iterator<? extends IDevice> queryClassDevices(IEntityClass entityClass, - Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort) { + MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort) { ArrayList<Iterator<Device>> iterators = new ArrayList<Iterator<Device>>(); ClassState classState = getClassState(entityClass); @@ -581,7 +585,7 @@ IFlowReconcileListener, IInfoProvider { } else { // index lookup Entity entity = - new Entity((macAddress == null ? 0 : macAddress), + new Entity(macAddress, vlan, ipv4Address, switchDPID, @@ -595,11 +599,11 @@ IFlowReconcileListener, IInfoProvider { return new MultiIterator<Device>(iterators.iterator()); } - protected Iterator<Device> getDeviceIteratorForQuery(Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort) { + protected Iterator<Device> getDeviceIteratorForQuery(MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort) { DeviceIndex index = null; if (secondaryIndexMap.size() > 0) { EnumSet<DeviceField> keys = @@ -614,7 +618,7 @@ IFlowReconcileListener, IInfoProvider { deviceIterator = deviceMap.values().iterator(); } else { // index lookup - Entity entity = new Entity((macAddress == null ? 0 : macAddress), + Entity entity = new Entity(macAddress, vlan, ipv4Address, switchDPID, @@ -642,12 +646,12 @@ IFlowReconcileListener, IInfoProvider { } @Override - public void addSuppressAPs(long swId, short port) { + public void addSuppressAPs(DatapathId swId, OFPort port) { suppressAPs.add(new SwitchPort(swId, port)); } @Override - public void removeSuppressAPs(long swId, short port) { + public void removeSuppressAPs(DatapathId swId, OFPort port) { suppressAPs.remove(new SwitchPort(swId, port)); } @@ -714,14 +718,14 @@ IFlowReconcileListener, IInfoProvider { } private void generateDeviceEvent(IDevice device, String reason) { - List<Integer> ipv4Addresses = - new ArrayList<Integer>(Arrays.asList(device.getIPv4Addresses())); + List<IPv4Address> ipv4Addresses = + new ArrayList<IPv4Address>(Arrays.asList(device.getIPv4Addresses())); List<SwitchPort> oldAps = new ArrayList<SwitchPort>(Arrays.asList(device.getOldAP())); List<SwitchPort> currentAps = new ArrayList<SwitchPort>(Arrays.asList(device.getAttachmentPoints())); - List<Short> vlanIds = - new ArrayList<Short>(Arrays.asList(device.getVlanId())); + List<VlanVid> vlanIds = + new ArrayList<VlanVid>(Arrays.asList(device.getVlanId())); evDevice.updateEventNoFlush( new DeviceEvent(device.getMACAddress(), @@ -771,7 +775,7 @@ IFlowReconcileListener, IInfoProvider { FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: - cntIncoming.updateCounterNoFlush(); + cntIncoming.increment(); return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx); default: @@ -803,19 +807,19 @@ IFlowReconcileListener, IInfoProvider { } protected Command reconcileFlow(OFMatchReconcile ofm) { - cntReconcileRequest.updateCounterNoFlush(); + cntReconcileRequest.increment(); // Extract source entity information Entity srcEntity = getEntityFromFlowMod(ofm.ofmWithSwDpid, true); if (srcEntity == null) { - cntReconcileNoSource.updateCounterNoFlush(); + cntReconcileNoSource.increment(); return Command.STOP; } // Find the device by source entity Device srcDevice = findDeviceByEntity(srcEntity); if (srcDevice == null) { - cntReconcileNoSource.updateCounterNoFlush(); + cntReconcileNoSource.increment(); return Command.STOP; } // Store the source device in the context @@ -830,9 +834,9 @@ IFlowReconcileListener, IInfoProvider { if (dstDevice != null) fcStore.put(ofm.cntx, CONTEXT_DST_DEVICE, dstDevice); else - cntReconcileNoDest.updateCounterNoFlush(); + cntReconcileNoDest.increment(); } else { - cntReconcileNoDest.updateCounterNoFlush(); + cntReconcileNoDest.increment(); } if (logger.isTraceEnabled()) { logger.trace("Reconciling flow: match={}, srcEntity={}, srcDev={}, " @@ -1189,7 +1193,7 @@ IFlowReconcileListener, IInfoProvider { Entity srcEntity = getSourceEntityFromPacket(eth, sw.getId(), pi.getInPort()); if (srcEntity == null) { - cntInvalidSource.updateCounterNoFlush(); + cntInvalidSource.increment(); return Command.STOP; } @@ -1204,7 +1208,7 @@ IFlowReconcileListener, IInfoProvider { // Learn/lookup device information Device srcDevice = learnDeviceByEntity(srcEntity); if (srcDevice == null) { - cntNoSource.updateCounterNoFlush(); + cntNoSource.increment(); return Command.STOP; } @@ -1214,7 +1218,7 @@ IFlowReconcileListener, IInfoProvider { // Find the device matching the destination from the entity // classes of the source. if (eth.getDestinationMAC().toLong() == 0) { - cntInvalidDest.updateCounterNoFlush(); + cntInvalidDest.increment(); return Command.STOP; } Entity dstEntity = getDestEntityFromPacket(eth); @@ -1225,9 +1229,9 @@ IFlowReconcileListener, IInfoProvider { if (dstDevice != null) fcStore.put(cntx, CONTEXT_DST_DEVICE, dstDevice); else - cntNoDest.updateCounterNoFlush(); + cntNoDest.increment(); } else { - cntNoDest.updateCounterNoFlush(); + cntNoDest.increment(); } if (logger.isTraceEnabled()) { @@ -1262,7 +1266,7 @@ IFlowReconcileListener, IInfoProvider { DHCPOption dhcpOption = dhcp.getOption( DHCPOptionCode.OptionCode_Hostname); if (dhcpOption != null) { - cntDhcpClientNameSnooped.updateCounterNoFlush(); + cntDhcpClientNameSnooped.increment(); srcDevice.dhcpClientName = new String(dhcpOption.getData()); } } @@ -1314,23 +1318,22 @@ IFlowReconcileListener, IInfoProvider { * @return the entity from the packet */ protected Entity getSourceEntityFromPacket(Ethernet eth, - long swdpid, - int port) { - byte[] dlAddrArr = eth.getSourceMACAddress(); - long dlAddr = Ethernet.toLong(dlAddrArr); - + DatapathId swdpid, + OFPort port) { + MacAddress dlAddr = MacAddress.of(eth.getSourceMACAddress()); + // Ignore broadcast/multicast source - if ((dlAddrArr[0] & 0x1) != 0) + if (dlAddr.isBroadcast() || dlAddr.isMulticast()) return null; // Ignore 0 source mac - if (dlAddr == 0) + if (dlAddr.getLong() == 0) return null; - short vlan = eth.getVlanID(); - int nwSrc = getSrcNwAddr(eth, dlAddr); + VlanVid vlan = VlanVid.ofVlan(eth.getVlanID()); + IPv4Address nwSrc = getSrcNwAddr(eth, dlAddr); return new Entity(dlAddr, - ((vlan >= 0) ? vlan : null), - ((nwSrc != 0) ? nwSrc : null), + vlan, + nwSrc, swdpid, port, new Date()); @@ -1342,8 +1345,8 @@ IFlowReconcileListener, IInfoProvider { * address in ARP data. */ protected void learnDeviceFromArpResponseData(Ethernet eth, - long swdpid, - int port) { + DatapathId swdpid, + OFPort port) { if (!(eth.getPayload() instanceof ARP)) return; ARP arp = (ARP) eth.getPayload(); @@ -1612,8 +1615,8 @@ IFlowReconcileListener, IInfoProvider { // attachment point port. Otherwise ignore. if (entity.hasSwitchPort() && !topology.isAttachmentPointPort(entity.getSwitchDPID(), - entity.getSwitchPort().shortValue())) { - cntDeviceOnInternalPortNotLearned.updateCounterNoFlush(); + entity.getSwitchPort())) { + cntDeviceOnInternalPortNotLearned.increment(); if (logger.isDebugEnabled()) { logger.debug("Not learning new device on internal" + " link: {}", entity); @@ -1624,7 +1627,7 @@ IFlowReconcileListener, IInfoProvider { // Before we create the new device also check if // the entity is allowed (e.g., for spoofing protection) if (!isEntityAllowed(entity, entityClass)) { - cntPacketNotAllowed.updateCounterNoFlush(); + cntPacketNotAllowed.increment(); if (logger.isDebugEnabled()) { logger.debug("PacketIn is not allowed {} {}", entityClass.getName(), entity); @@ -1652,7 +1655,7 @@ IFlowReconcileListener, IInfoProvider { // We need to count and log here. If we log earlier we could // hit a concurrent modification and restart the dev creation // and potentially count the device twice. - cntNewDevice.updateCounterNoFlush(); + cntNewDevice.increment(); if (logger.isDebugEnabled()) { logger.debug("New device created: {} deviceKey={}, entity={}", new Object[]{device, deviceKey, entity}); @@ -1666,7 +1669,7 @@ IFlowReconcileListener, IInfoProvider { } // if it gets here, we have a pre-existing Device for this Entity if (!isEntityAllowed(entity, device.getEntityClass())) { - cntPacketNotAllowed.updateCounterNoFlush(); + cntPacketNotAllowed.increment(); if (logger.isDebugEnabled()) { logger.info("PacketIn is not allowed {} {}", device.getEntityClass().getName(), entity); @@ -1678,8 +1681,8 @@ IFlowReconcileListener, IInfoProvider { // the chain. if (entity.hasSwitchPort() && !topology.isAttachmentPointPort(entity.getSwitchDPID(), - entity.getSwitchPort().shortValue())) { - cntPacketOnInternalPortForKnownDevice.updateCounterNoFlush(); + entity.getSwitchPort())) { + cntPacketOnInternalPortForKnownDevice.increment(); break; } int entityindex = -1; @@ -1723,9 +1726,9 @@ IFlowReconcileListener, IInfoProvider { // We need to count here after all the possible "continue" // statements in this branch - cntNewEntity.updateCounterNoFlush(); + cntNewEntity.increment(); if (changedFields.size() > 0) { - cntDeviceChanged.updateCounterNoFlush(); + cntDeviceChanged.increment(); deviceUpdates = updateUpdates(deviceUpdates, new DeviceUpdate(newDevice, CHANGE, @@ -1738,8 +1741,8 @@ IFlowReconcileListener, IInfoProvider { if (entity.hasSwitchPort()) { boolean moved = device.updateAttachmentPoint(entity.getSwitchDPID(), - entity.getSwitchPort().shortValue(), - entity.getLastSeenTimestamp().getTime()); + entity.getSwitchPort(), + entity.getLastSeenTimestamp()); // TODO: use update mechanism instead of sending the // notification directly if (moved) { @@ -1986,7 +1989,7 @@ IFlowReconcileListener, IInfoProvider { * Clean up expired entities/devices */ protected void cleanupEntities () { - cntCleanupEntitiesRuns.updateCounterWithFlush(); + cntCleanupEntitiesRuns.increment(); Calendar c = Calendar.getInstance(); c.add(Calendar.MILLISECOND, -ENTITY_TIMEOUT); @@ -2019,7 +2022,7 @@ IFlowReconcileListener, IInfoProvider { break; } - cntEntityRemovedTimeout.updateCounterWithFlush(); + cntEntityRemovedTimeout.increment(); for (Entity e : toRemove) { removeEntity(e, d.getEntityClass(), d.getDeviceKey(), toKeep); } @@ -2055,7 +2058,7 @@ IFlowReconcileListener, IInfoProvider { if (update != null) { // need to count after all possibly continue stmts in // this branch - cntDeviceChanged.updateCounterWithFlush(); + cntDeviceChanged.increment(); deviceUpdates.add(update); } } else { @@ -2067,7 +2070,7 @@ IFlowReconcileListener, IInfoProvider { d = deviceMap.get(d.getDeviceKey()); if (null != d) continue; - cntDeviceDeleted.updateCounterWithFlush(); + cntDeviceDeleted.increment(); } deviceUpdates.add(update); } @@ -2125,11 +2128,11 @@ IFlowReconcileListener, IInfoProvider { } } - private EnumSet<DeviceField> getEntityKeys(Long macAddress, - Short vlan, - Integer ipv4Address, - Long switchDPID, - Integer switchPort) { + private EnumSet<DeviceField> getEntityKeys(MacAddress macAddress, + VlanVid vlan, + IPv4Address ipv4Address, + DatapathId switchDPID, + OFPort switchPort) { // FIXME: vlan==null is a valid search. Need to handle this // case correctly. Note that the code will still work correctly. // But we might do a full device search instead of using an index. @@ -2183,8 +2186,8 @@ IFlowReconcileListener, IInfoProvider { for (Entity entity : entities) { if (entity.switchDPID != null && entity.switchPort != null) { AttachmentPoint aP = - new AttachmentPoint(entity.switchDPID.longValue(), - entity.switchPort.shortValue(), 0); + new AttachmentPoint(entity.switchDPID, + entity.switchPort, new Date(0)); newPossibleAPs.add(aP); } } @@ -2241,7 +2244,7 @@ IFlowReconcileListener, IInfoProvider { * @param updates the updates to process. */ protected void sendDeviceMovedNotification(Device d) { - cntDeviceMoved.updateCounterNoFlush(); + cntDeviceMoved.increment(); deviceSyncManager.storeDevice(d); List<IDeviceListener> listeners = deviceListeners.getOrderedListeners(); if (listeners != null) { @@ -2300,7 +2303,7 @@ IFlowReconcileListener, IInfoProvider { return false; } - cntDeviceReclassifyDelete.updateCounterNoFlush(); + cntDeviceReclassifyDelete.increment(); LinkedList<DeviceUpdate> deviceUpdates = new LinkedList<DeviceUpdate>(); // delete this device and then re-learn all the entities @@ -2385,7 +2388,7 @@ IFlowReconcileListener, IInfoProvider { writeUpdatedDeviceToStorage(d); lastWriteTimes.put(d.getDeviceKey(), now); } else { - cntDeviceStoreThrottled.updateCounterWithFlush(); + cntDeviceStoreThrottled.increment(); } } @@ -2406,12 +2409,12 @@ IFlowReconcileListener, IInfoProvider { // TODO: should probably do versioned delete. OTOH, even // if we accidentally delete, we'll write it again after // the next entity .... - cntDeviceRemovedFromStore.updateCounterWithFlush(); + cntDeviceRemovedFromStore.increment(); storeClient.delete(DeviceSyncRepresentation.computeKey(d)); } catch(ObsoleteVersionException e) { // FIXME } catch (SyncException e) { - cntSyncException.updateCounterWithFlush(); + cntSyncException.increment(); logger.error("Could not remove device " + d + " from store", e); } } @@ -2423,14 +2426,14 @@ IFlowReconcileListener, IInfoProvider { */ private void removeDevice(Versioned<DeviceSyncRepresentation> dev) { try { - cntDeviceRemovedFromStore.updateCounterWithFlush(); + cntDeviceRemovedFromStore.increment(); storeClient.delete(dev.getValue().getKey(), dev.getVersion()); } catch(ObsoleteVersionException e) { // Key was locally modified by another thread. // Do not delete and ignore. } catch(SyncException e) { - cntSyncException.updateCounterWithFlush(); + cntSyncException.increment(); logger.error("Failed to remove device entry for " + dev.toString() + " from store.", e); } @@ -2444,13 +2447,13 @@ IFlowReconcileListener, IInfoProvider { if (logger.isDebugEnabled()) { logger.debug("Transitioning to MASTER role"); } - cntTransitionToMaster.updateCounterWithFlush(); + cntTransitionToMaster.increment(); IClosableIterator<Map.Entry<String,Versioned<DeviceSyncRepresentation>>> iter = null; try { iter = storeClient.entries(); } catch (SyncException e) { - cntSyncException.updateCounterWithFlush(); + cntSyncException.increment(); logger.error("Failed to read devices from sync store", e); return; } @@ -2462,7 +2465,7 @@ IFlowReconcileListener, IInfoProvider { versionedDevice.getValue(); if (storedDevice == null) continue; - cntDevicesFromStore.updateCounterWithFlush(); + cntDevicesFromStore.increment(); for(SyncEntity se: storedDevice.getEntities()) { learnDeviceByEntity(se.asEntity()); } @@ -2482,7 +2485,7 @@ IFlowReconcileListener, IInfoProvider { */ private void writeUpdatedDeviceToStorage(Device device) { try { - cntDeviceStrored.updateCounterWithFlush(); + cntDeviceStrored.increment(); // FIXME: use a versioned put DeviceSyncRepresentation storeDevice = new DeviceSyncRepresentation(device); @@ -2491,7 +2494,7 @@ IFlowReconcileListener, IInfoProvider { // FIXME: what's the right behavior here. Can the store client // even throw this error? } catch (SyncException e) { - cntSyncException.updateCounterWithFlush(); + cntSyncException.increment(); logger.error("Could not write device " + device + " to sync store:", e); } @@ -2515,7 +2518,7 @@ IFlowReconcileListener, IInfoProvider { private void consolidateStore() { if (!isMaster) return; - cntConsolidateStoreRuns.updateCounterWithFlush(); + cntConsolidateStoreRuns.increment(); if (logger.isDebugEnabled()) { logger.debug("Running consolidateStore."); } @@ -2524,7 +2527,7 @@ IFlowReconcileListener, IInfoProvider { try { iter = storeClient.entries(); } catch (SyncException e) { - cntSyncException.updateCounterWithFlush(); + cntSyncException.increment(); logger.error("Failed to read devices from sync store", e); return; } @@ -2561,7 +2564,7 @@ IFlowReconcileListener, IInfoProvider { + "corresponding live device", storedDevice.getKey()); } - cntConsolidateStoreDevicesRemoved.updateCounterWithFlush(); + cntConsolidateStoreDevicesRemoved.increment(); removeDevice(versionedDevice); } } @@ -2596,24 +2599,24 @@ IFlowReconcileListener, IInfoProvider { */ private class DeviceEvent { @EventColumn(name = "MAC", description = EventFieldType.MAC) - private final long macAddress; - @EventColumn(name = "IPs", description = EventFieldType.LIST_IPV4) - private final List<Integer> ipv4Addresses; + private final MacAddress macAddress; + @EventColumn(name = "IPs", description = EventFieldType.IPv4) + private final List<IPv4Address> ipv4Addresses; @EventColumn(name = "Old Attachment Points", - description = EventFieldType.LIST_ATTACHMENT_POINT) + description = EventFieldType.COLLECTION_ATTACHMENT_POINT) private final List<SwitchPort> oldAttachmentPoints; @EventColumn(name = "Current Attachment Points", - description = EventFieldType.LIST_ATTACHMENT_POINT) + description = EventFieldType.COLLECTION_ATTACHMENT_POINT) private final List<SwitchPort> currentAttachmentPoints; - @EventColumn(name = "VLAN IDs", description = EventFieldType.LIST_OBJECT) - private final List<Short> vlanIds; + @EventColumn(name = "VLAN IDs", description = EventFieldType.COLLECTION_OBJECT) + private final List<VlanVid> vlanIds; @EventColumn(name = "Reason", description = EventFieldType.STRING) private final String reason; - public DeviceEvent(long macAddress, List<Integer> ipv4Addresses, + public DeviceEvent(MacAddress macAddress, List<IPv4Address> ipv4Addresses, List<SwitchPort> oldAttachmentPoints, List<SwitchPort> currentAttachmentPoints, - List<Short> vlanIds, String reason) { + List<VlanVid> vlanIds, String reason) { super(); this.macAddress = macAddress; this.ipv4Addresses = ipv4Addresses; diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java index 42bfb01321cfc704d9578672630893bff31d4e0e..b1c395d4c9664553550685125f686bdf87508283 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java @@ -6,9 +6,14 @@ import java.util.Collections; import java.util.Date; import java.util.EnumSet; import java.util.List; -import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; +import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField; import net.floodlightcontroller.devicemanager.SwitchPort; import com.fasterxml.jackson.annotation.JsonProperty; @@ -16,15 +21,15 @@ import com.fasterxml.jackson.annotation.JsonProperty; public class DeviceSyncRepresentation { public static class SyncEntity implements Comparable<SyncEntity> { @JsonProperty - public long macAddress; + public MacAddress macAddress; @JsonProperty - public Integer ipv4Address; + public IPv4Address ipv4Address; @JsonProperty - public Short vlan; + public VlanVid vlan; @JsonProperty - public Long switchDPID; + public DatapathId switchDPID; @JsonProperty - public Integer switchPort; + public OFPort switchPort; @JsonProperty public Date lastSeenTimestamp; @JsonProperty diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java index db8d8e9fb3ff92256e0e9db55751e9345e6765fa..39a8d79cd7c67b8e08522943bc97055b1d45745d 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java @@ -22,11 +22,15 @@ import java.util.Date; import net.floodlightcontroller.core.web.serializers.IPv4Serializer; import net.floodlightcontroller.core.web.serializers.MACSerializer; import net.floodlightcontroller.core.web.serializers.DPIDSerializer; -import net.floodlightcontroller.packet.IPv4; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; /** * An entity on the network is a visible trace of a device that corresponds @@ -52,30 +56,30 @@ public class Entity implements Comparable<Entity> { /** * The MAC address associated with this entity */ - protected long macAddress; + protected MacAddress macAddress; /** * The IP address associated with this entity, or null if no IP learned * from the network observation associated with this entity */ - protected Integer ipv4Address; + protected IPv4Address ipv4Address; /** * The VLAN tag on this entity, or null if untagged */ - protected Short vlan; + protected VlanVid vlan; /** * The DPID of the switch for the ingress point for this entity, * or null if not present */ - protected Long switchDPID; + protected DatapathId switchDPID; /** * The port number of the switch for the ingress point for this entity, * or null if not present */ - protected Integer switchPort; + protected OFPort switchPort; /** * The last time we observed this entity on the network @@ -108,8 +112,8 @@ public class Entity implements Comparable<Entity> { * @param switchPort * @param lastSeenTimestamp */ - public Entity(long macAddress, Short vlan, - Integer ipv4Address, Long switchDPID, Integer switchPort, + public Entity(MacAddress macAddress, VlanVid vlan, + IPv4Address ipv4Address, DatapathId switchDPID, OFPort switchPort, Date lastSeenTimestamp) { this.macAddress = macAddress; this.ipv4Address = ipv4Address; @@ -125,25 +129,25 @@ public class Entity implements Comparable<Entity> { // *************** @JsonSerialize(using=MACSerializer.class) - public long getMacAddress() { + public MacAddress getMacAddress() { return macAddress; } @JsonSerialize(using=IPv4Serializer.class) - public Integer getIpv4Address() { + public IPv4Address getIpv4Address() { return ipv4Address; } - public Short getVlan() { + public VlanVid getVlan() { return vlan; } @JsonSerialize(using=DPIDSerializer.class) - public Long getSwitchDPID() { + public DatapathId getSwitchDPID() { return switchDPID; } - public Integer getSwitchPort() { + public OFPort getSwitchPort() { return switchPort; } @@ -185,7 +189,7 @@ public class Entity implements Comparable<Entity> { hashCode = 1; hashCode = prime * hashCode + ((ipv4Address == null) ? 0 : ipv4Address.hashCode()); - hashCode = prime * hashCode + (int) (macAddress ^ (macAddress >>> 32)); + hashCode = prime * hashCode + (int) (macAddress.getLong() ^ (macAddress.getLong() >>> 32)); hashCode = prime * hashCode + ((switchDPID == null) ? 0 : switchDPID.hashCode()); hashCode = prime * hashCode @@ -223,16 +227,15 @@ public class Entity implements Comparable<Entity> { public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Entity [macAddress="); - builder.append(HexString.toHexString(macAddress, 6)); + builder.append(macAddress.toString()); builder.append(", ipv4Address="); - builder.append(IPv4.fromIPv4Address(ipv4Address==null ? - 0 : ipv4Address.intValue())); + builder.append(ipv4Address.toString()); builder.append(", vlan="); - builder.append(vlan); + builder.append(vlan.getVlan()); builder.append(", switchDPID="); - builder.append(switchDPID); + builder.append(switchDPID.toString()); builder.append(", switchPort="); - builder.append(switchPort); + builder.append(switchPort.getPortNumber()); builder.append(", lastSeenTimestamp="); builder.append(lastSeenTimestamp == null? "null" : lastSeenTimestamp.getTime()); builder.append(", activeSince="); @@ -243,8 +246,8 @@ public class Entity implements Comparable<Entity> { @Override public int compareTo(Entity o) { - if (macAddress < o.macAddress) return -1; - if (macAddress > o.macAddress) return 1; + if (macAddress.getLong() < o.macAddress.getLong()) return -1; + if (macAddress.getLong() > o.macAddress.getLong()) return 1; int r; if (switchDPID == null) diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java index 13a78a49accfa001c51fb3260325179abc362a46..a1e7160b2b4987ffa2d87a07b3d6367a191ba43c 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java @@ -89,8 +89,8 @@ public class IndexedEntity { switch (f) { case MAC: hashCode = prime * hashCode - + (int) (entity.macAddress ^ - (entity.macAddress >>> 32)); + + (int) (entity.macAddress.getLong() ^ + (entity.macAddress.getLong() >>> 32)); break; case IPV4: hashCode = prime * hashCode diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java index 21dc8aed6ca937f3123e9a00971ee8b0fc13fd80..6b6b5578f06dbe18416fc0eb166a7245dd076f4f 100644 --- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java +++ b/src/main/java/net/floodlightcontroller/firewall/Firewall.java @@ -24,9 +24,16 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.EthType; +import org.projectfloodlight.openflow.types.IPv4AddressWithMask; +import org.projectfloodlight.openflow.types.IpProtocol; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.TransportPort; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IOFMessageListener; @@ -35,11 +42,11 @@ 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.core.IFloodlightProviderService; import net.floodlightcontroller.devicemanager.IDeviceService; import java.util.ArrayList; + import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.restserver.IRestApiService; @@ -184,7 +191,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, try { r.ruleid = Integer .parseInt((String) row.get(COLUMN_RULEID)); - r.dpid = Long.parseLong((String) row.get(COLUMN_DPID)); + r.dpid = DatapathId.of((String) row.get(COLUMN_DPID)); for (String key : row.keySet()) { if (row.get(key) == null) @@ -196,58 +203,58 @@ public class Firewall implements IFirewallService, IOFMessageListener, } else if (key.equals(COLUMN_IN_PORT)) { - r.in_port = Short.parseShort((String) row - .get(COLUMN_IN_PORT)); + r.in_port = OFPort.of(Integer.parseInt((String) row + .get(COLUMN_IN_PORT))); } else if (key.equals(COLUMN_DL_SRC)) { - r.dl_src = Long.parseLong((String) row - .get(COLUMN_DL_SRC)); + r.dl_src = MacAddress.of(Long.parseLong((String) row + .get(COLUMN_DL_SRC))); } else if (key.equals(COLUMN_DL_DST)) { - r.dl_dst = Long.parseLong((String) row - .get(COLUMN_DL_DST)); + r.dl_dst = MacAddress.of(Long.parseLong((String) row + .get(COLUMN_DL_DST))); } else if (key.equals(COLUMN_DL_TYPE)) { - r.dl_type = Short.parseShort((String) row - .get(COLUMN_DL_TYPE)); + r.dl_type = EthType.of(Integer.parseInt((String) row + .get(COLUMN_DL_TYPE))); } else if (key.equals(COLUMN_NW_SRC_PREFIX)) { - r.nw_src_prefix = Integer.parseInt((String) row - .get(COLUMN_NW_SRC_PREFIX)); + r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row + .get(COLUMN_NW_SRC_PREFIX)), r.nw_src_prefix_and_mask.getMask().getInt()); } else if (key.equals(COLUMN_NW_SRC_MASKBITS)) { - r.nw_src_maskbits = Integer.parseInt((String) row - .get(COLUMN_NW_SRC_MASKBITS)); + r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(r.nw_src_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row + .get(COLUMN_NW_SRC_MASKBITS))); } else if (key.equals(COLUMN_NW_DST_PREFIX)) { - r.nw_dst_prefix = Integer.parseInt((String) row - .get(COLUMN_NW_DST_PREFIX)); + r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row + .get(COLUMN_NW_DST_PREFIX)), r.nw_dst_prefix_and_mask.getMask().getInt()); } else if (key.equals(COLUMN_NW_DST_MASKBITS)) { - r.nw_dst_maskbits = Integer.parseInt((String) row - .get(COLUMN_NW_DST_MASKBITS)); + r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(r.nw_dst_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row + .get(COLUMN_NW_DST_MASKBITS))); } else if (key.equals(COLUMN_NW_PROTO)) { - r.nw_proto = Short.parseShort((String) row - .get(COLUMN_NW_PROTO)); + r.nw_proto = IpProtocol.of(Short.parseShort((String) row + .get(COLUMN_NW_PROTO))); } else if (key.equals(COLUMN_TP_SRC)) { - r.tp_src = Short.parseShort((String) row - .get(COLUMN_TP_SRC)); + r.tp_src = TransportPort.of(Integer.parseInt((String) row + .get(COLUMN_TP_SRC))); } else if (key.equals(COLUMN_TP_DST)) { - r.tp_dst = Short.parseShort((String) row - .get(COLUMN_TP_DST)); + r.tp_dst = TransportPort.of(Integer.parseInt((String) row + .get(COLUMN_TP_DST))); } else if (key.equals(COLUMN_WILDCARD_DPID)) { @@ -452,18 +459,18 @@ public class Firewall implements IFirewallService, IOFMessageListener, // add rule to database Map<String, Object> entry = new HashMap<String, Object>(); entry.put(COLUMN_RULEID, Integer.toString(rule.ruleid)); - entry.put(COLUMN_DPID, Long.toString(rule.dpid)); - entry.put(COLUMN_IN_PORT, Short.toString(rule.in_port)); - entry.put(COLUMN_DL_SRC, Long.toString(rule.dl_src)); - entry.put(COLUMN_DL_DST, Long.toString(rule.dl_dst)); - entry.put(COLUMN_DL_TYPE, Short.toString(rule.dl_type)); - entry.put(COLUMN_NW_SRC_PREFIX, Integer.toString(rule.nw_src_prefix)); - entry.put(COLUMN_NW_SRC_MASKBITS, Integer.toString(rule.nw_src_maskbits)); - entry.put(COLUMN_NW_DST_PREFIX, Integer.toString(rule.nw_dst_prefix)); - entry.put(COLUMN_NW_DST_MASKBITS, Integer.toString(rule.nw_dst_maskbits)); - entry.put(COLUMN_NW_PROTO, Short.toString(rule.nw_proto)); - entry.put(COLUMN_TP_SRC, Integer.toString(rule.tp_src)); - entry.put(COLUMN_TP_DST, Integer.toString(rule.tp_dst)); + entry.put(COLUMN_DPID, Long.toString(rule.dpid.getLong())); + entry.put(COLUMN_IN_PORT, Integer.toString(rule.in_port.getPortNumber())); + entry.put(COLUMN_DL_SRC, Long.toString(rule.dl_src.getLong())); + entry.put(COLUMN_DL_DST, Long.toString(rule.dl_dst.getLong())); + entry.put(COLUMN_DL_TYPE, Integer.toString(rule.dl_type.getValue())); + entry.put(COLUMN_NW_SRC_PREFIX, Integer.toString(rule.nw_src_prefix_and_mask.getValue().getInt())); + entry.put(COLUMN_NW_SRC_MASKBITS, Integer.toString(rule.nw_src_prefix_and_mask.getMask().getInt())); + entry.put(COLUMN_NW_DST_PREFIX, Integer.toString(rule.nw_dst_prefix_and_mask.getValue().getInt())); + entry.put(COLUMN_NW_DST_MASKBITS, Integer.toString(rule.nw_dst_prefix_and_mask.getMask().getInt())); + entry.put(COLUMN_NW_PROTO, Short.toString(rule.nw_proto.getIpProtocolNumber())); + entry.put(COLUMN_TP_SRC, Integer.toString(rule.tp_src.getPort())); + entry.put(COLUMN_TP_DST, Integer.toString(rule.tp_dst.getPort())); entry.put(COLUMN_WILDCARD_DPID, Boolean.toString(rule.wildcard_dpid)); entry.put(COLUMN_WILDCARD_IN_PORT, diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java index f457ce8d9e85510f91fdefe2bb2f3ac84276eec4..bee8fddef5942d16806c3cef144ded5a01dcfd3b 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java @@ -18,7 +18,15 @@ package net.floodlightcontroller.firewall; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.openflow.protocol.OFMatch; + +import org.projectfloodlight.openflow.protocol.match.MatchField; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.EthType; +import org.projectfloodlight.openflow.types.IPv4AddressWithMask; +import org.projectfloodlight.openflow.types.IpProtocol; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.TransportPort; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPacket; @@ -30,18 +38,18 @@ import net.floodlightcontroller.packet.UDP; public class FirewallRule implements Comparable<FirewallRule> { public int ruleid; - public long dpid; - public short in_port; - public long dl_src; - public long dl_dst; - public short dl_type; - public int nw_src_prefix; - public int nw_src_maskbits; - public int nw_dst_prefix; - public int nw_dst_maskbits; - public short nw_proto; - public short tp_src; - public short tp_dst; + public DatapathId dpid; + public OFPort in_port; + public MacAddress dl_src; + public MacAddress dl_dst; + public EthType dl_type; + public IPv4AddressWithMask nw_src_prefix_and_mask; + //public int nw_src_maskbits; + public IPv4AddressWithMask nw_dst_prefix_and_mask; + //public int nw_dst_maskbits; + public IpProtocol nw_proto; + public TransportPort tp_src; + public TransportPort tp_dst; public boolean wildcard_dpid; public boolean wildcard_in_port; @@ -67,18 +75,18 @@ public class FirewallRule implements Comparable<FirewallRule> { } public FirewallRule() { - this.in_port = 0; - this.dl_src = 0; - this.nw_src_prefix = 0; - this.nw_src_maskbits = 0; - this.dl_dst = 0; - this.nw_proto = 0; - this.tp_src = 0; - this.tp_dst = 0; - this.dl_dst = 0; - this.nw_dst_prefix = 0; - this.nw_dst_maskbits = 0; - this.dpid = -1; + this.in_port = OFPort.ZERO; + this.dl_src = MacAddress.NONE; + this.nw_src_prefix_and_mask = IPv4AddressWithMask.NONE; + //this.nw_src_maskbits = 0; + this.dl_dst = MacAddress.NONE; + this.nw_proto = IpProtocol.NONE; + this.tp_src = TransportPort.NONE; + this.tp_dst = TransportPort.NONE; + this.dl_dst = MacAddress.NONE; + this.nw_dst_prefix_and_mask = IPv4AddressWithMask.NONE; + //this.nw_dst_maskbits = 0; + this.dpid = DatapathId.NONE; this.wildcard_dpid = true; this.wildcard_in_port = true; this.wildcard_dl_src = true; @@ -88,7 +96,7 @@ public class FirewallRule implements Comparable<FirewallRule> { this.wildcard_nw_dst = true; this.wildcard_nw_proto = true; this.wildcard_tp_src = true; - this.wildcard_tp_dst = true; + this.wildcard_tp_dst = true; this.priority = 0; this.action = FirewallAction.ALLOW; this.ruleid = 0; @@ -132,23 +140,23 @@ public class FirewallRule implements Comparable<FirewallRule> { public boolean isSameAs(FirewallRule r) { if (this.action != r.action || this.wildcard_dl_type != r.wildcard_dl_type - || (this.wildcard_dl_type == false && this.dl_type != r.dl_type) + || (this.wildcard_dl_type == false && !this.dl_type.equals(r.dl_type)) || this.wildcard_tp_src != r.wildcard_tp_src - || (this.wildcard_tp_src == false && this.tp_src != r.tp_src) + || (this.wildcard_tp_src == false && !this.tp_src.equals(r.tp_src)) || this.wildcard_tp_dst != r.wildcard_tp_dst - || (this.wildcard_tp_dst == false &&this.tp_dst != r.tp_dst) + || (this.wildcard_tp_dst == false && !this.tp_dst.equals(r.tp_dst)) || this.wildcard_dpid != r.wildcard_dpid - || (this.wildcard_dpid == false && this.dpid != r.dpid) + || (this.wildcard_dpid == false && !this.dpid.equals(r.dpid)) || this.wildcard_in_port != r.wildcard_in_port - || (this.wildcard_in_port == false && this.in_port != r.in_port) + || (this.wildcard_in_port == false && !this.in_port.equals(r.in_port)) || this.wildcard_nw_src != r.wildcard_nw_src - || (this.wildcard_nw_src == false && (this.nw_src_prefix != r.nw_src_prefix || this.nw_src_maskbits != r.nw_src_maskbits)) + || (this.wildcard_nw_src == false && !this.nw_src_prefix_and_mask.equals(r.nw_src_prefix_and_mask)) || this.wildcard_dl_src != r.wildcard_dl_src - || (this.wildcard_dl_src == false && this.dl_src != r.dl_src) + || (this.wildcard_dl_src == false && !this.dl_src.equals(r.dl_src)) || this.wildcard_nw_proto != r.wildcard_nw_proto - || (this.wildcard_nw_proto == false && this.nw_proto != r.nw_proto) + || (this.wildcard_nw_proto == false && !this.nw_proto.equals(r.nw_proto)) || this.wildcard_nw_dst != r.wildcard_nw_dst - || (this.wildcard_nw_dst == false && (this.nw_dst_prefix != r.nw_dst_prefix || this.nw_dst_maskbits != r.nw_dst_maskbits)) + || (this.wildcard_nw_dst == false && !this.nw_dst_prefix_and_mask.equals(r.nw_dst_prefix_and_mask)) || this.wildcard_dl_dst != r.wildcard_dl_dst || (this.wildcard_dl_dst == false && this.dl_dst != r.dl_dst)) { return false; @@ -171,7 +179,7 @@ public class FirewallRule implements Comparable<FirewallRule> { * method to derive wildcards for the decision to be taken * @return true if the rule matches the given packet-in, false otherwise */ - public boolean matchesFlow(long switchDpid, short inPort, Ethernet packet, + public boolean matchesFlow(DatapathId switchDpid, OFPort inPort, Ethernet packet, WildcardsPair wildcards) { IPacket pkt = packet.getPayload(); @@ -187,35 +195,39 @@ public class FirewallRule implements Comparable<FirewallRule> { short pkt_tp_dst = 0; // switchID matches? - if (wildcard_dpid == false && dpid != switchDpid) + if (wildcard_dpid == false && !dpid.equals(switchDpid)) return false; // in_port matches? - if (wildcard_in_port == false && in_port != inPort) + if (wildcard_in_port == false && !in_port.equals(inPort)) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_IN_PORT; + //wildcards.drop &= ~OFMatch.OFPFW_IN_PORT; + wildcards.drop.setExact(MatchField.IN_PORT, this.in_port); } else { - wildcards.allow &= ~OFMatch.OFPFW_IN_PORT; + //wildcards.allow &= ~OFMatch.OFPFW_IN_PORT; + wildcards.allow.setExact(MatchField.IN_PORT, this.in_port); } // mac address (src and dst) match? - if (wildcard_dl_src == false - && dl_src != packet.getSourceMAC().toLong()) + if (wildcard_dl_src == false && !dl_src.equals(packet.getSourceMAC())) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_DL_SRC; + //wildcards.drop &= ~OFMatch.OFPFW_DL_SRC; + wildcards.drop.setExact(MatchField.ETH_SRC, this.dl_src); } else { - wildcards.allow &= ~OFMatch.OFPFW_DL_SRC; + //wildcards.allow &= ~OFMatch.OFPFW_DL_SRC; + wildcards.allow.setExact(MatchField.ETH_SRC, this.dl_src); } - if (wildcard_dl_dst == false - && dl_dst != packet.getDestinationMAC().toLong()) + if (wildcard_dl_dst == false && !dl_dst.equals(packet.getDestinationMAC())) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_DL_DST; + //wildcards.drop &= ~OFMatch.OFPFW_DL_DST; + wildcards.drop.setExact(MatchField.ETH_DST, this.dl_dst); } else { - wildcards.allow &= ~OFMatch.OFPFW_DL_DST; + //wildcards.allow &= ~OFMatch.OFPFW_DL_DST; + wildcards.allow.setExact(MatchField.ETH_DST, this.dl_dst); } // dl_type check: ARP, IP @@ -223,103 +235,128 @@ public class FirewallRule implements Comparable<FirewallRule> { // if this is not an ARP rule but the pkt is ARP, // return false match - no need to continue protocol specific check if (wildcard_dl_type == false) { - if (dl_type == Ethernet.TYPE_ARP) { - if (packet.getEtherType() != Ethernet.TYPE_ARP) + if (dl_type.equals(EthType.ARP)) { + if (packet.getEtherType() != EthType.ARP.getValue()) return false; else { if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; + //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; + wildcards.drop.setExact(MatchField.ETH_TYPE, this.dl_type); } else { - wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE; + //wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE; + wildcards.allow.setExact(MatchField.ETH_TYPE, this.dl_type); } } - } else if (dl_type == Ethernet.TYPE_IPv4) { - if (packet.getEtherType() != Ethernet.TYPE_IPv4) + } else if (dl_type.equals(EthType.IPv4)) { + if (packet.getEtherType() != EthType.IPv4.getValue()) return false; else { if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; + //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; + wildcards.drop.setExact(MatchField.IP_PROTO, this.nw_proto); } else { - wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO; + //wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO; + wildcards.allow.setExact(MatchField.IP_PROTO, this.nw_proto); } // IP packets, proceed with ip address check pkt_ip = (IPv4) pkt; // IP addresses (src and dst) match? - if (wildcard_nw_src == false - && this.matchIPAddress(nw_src_prefix, - nw_src_maskbits, pkt_ip.getSourceAddress()) == false) + if (wildcard_nw_src == false && this.matchIPAddress(nw_src_prefix_and_mask.getValue().getInt(), nw_src_prefix_and_mask.getMask().getInt(), pkt_ip.getSourceAddress()) == false) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL; - wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); + //wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL; + //wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); + wildcards.drop.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); } else { - wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL; - wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); + //wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL; + //wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); + wildcards.allow.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); } - if (wildcard_nw_dst == false - && this.matchIPAddress(nw_dst_prefix, - nw_dst_maskbits, - pkt_ip.getDestinationAddress()) == false) + if (wildcard_nw_dst == false && this.matchIPAddress(nw_dst_prefix_and_mask.getValue().getInt(), nw_dst_prefix_and_mask.getMask().getInt(), pkt_ip.getDestinationAddress()) == false) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL; - wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); + //wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL; + //wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); + wildcards.drop.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); } else { - wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL; - wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); + //wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL; + //wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); + wildcards.allow.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); } // nw_proto check if (wildcard_nw_proto == false) { - if (nw_proto == IPv4.PROTOCOL_TCP) { - if (pkt_ip.getProtocol() != IPv4.PROTOCOL_TCP) + if (nw_proto.equals(IpProtocol.TCP)) { + if ((short) pkt_ip.getProtocol() != IpProtocol.TCP.getIpProtocolNumber()) return false; else { pkt_tcp = (TCP) pkt_ip.getPayload(); pkt_tp_src = pkt_tcp.getSourcePort(); pkt_tp_dst = pkt_tcp.getDestinationPort(); } - } else if (nw_proto == IPv4.PROTOCOL_UDP) { - if (pkt_ip.getProtocol() != IPv4.PROTOCOL_UDP) + } else if (nw_proto.equals(IpProtocol.UDP)) { + if ((short) pkt_ip.getProtocol() != IpProtocol.UDP.getIpProtocolNumber()) return false; else { pkt_udp = (UDP) pkt_ip.getPayload(); pkt_tp_src = pkt_udp.getSourcePort(); pkt_tp_dst = pkt_udp.getDestinationPort(); } - } else if (nw_proto == IPv4.PROTOCOL_ICMP) { - if (pkt_ip.getProtocol() != IPv4.PROTOCOL_ICMP) + } else if (nw_proto.equals(IpProtocol.ICMP)) { + if ((short) pkt_ip.getProtocol() != IpProtocol.ICMP.getIpProtocolNumber()) return false; else { // nothing more needed for ICMP } } if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; + //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; + wildcards.drop.setExact(MatchField.IP_PROTO, this.nw_proto); } else { - wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO; + //wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO; + wildcards.allow.setExact(MatchField.IP_PROTO, this.nw_proto); } // TCP/UDP source and destination ports match? if (pkt_tcp != null || pkt_udp != null) { // does the source port match? - if (tp_src != 0 && tp_src != pkt_tp_src) + if (tp_src.getPort() != 0 && tp_src.getPort() != pkt_tp_src) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_TP_SRC; + //wildcards.drop &= ~OFMatch.OFPFW_TP_SRC; + if (pkt_tcp != null) { + wildcards.drop.setExact(MatchField.TCP_SRC, this.tp_src); + } else { + wildcards.drop.setExact(MatchField.UDP_SRC, this.tp_src); + } } else { - wildcards.allow &= ~OFMatch.OFPFW_TP_SRC; + //wildcards.allow &= ~OFMatch.OFPFW_TP_SRC; + if (pkt_tcp != null) { + wildcards.allow.setExact(MatchField.TCP_SRC, this.tp_src); + } else { + wildcards.allow.setExact(MatchField.UDP_SRC, this.tp_src); + } } // does the destination port match? - if (tp_dst != 0 && tp_dst != pkt_tp_dst) + if (tp_dst.getPort() != 0 && tp_dst.getPort() != pkt_tp_dst) return false; if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_TP_DST; + //wildcards.drop &= ~OFMatch.OFPFW_TP_DST; + if (pkt_tcp != null) { + wildcards.drop.setExact(MatchField.TCP_DST, this.tp_dst); + } else { + wildcards.drop.setExact(MatchField.UDP_DST, this.tp_dst); + } } else { - wildcards.allow &= ~OFMatch.OFPFW_TP_DST; + //wildcards.allow &= ~OFMatch.OFPFW_TP_DST; + if (pkt_tcp != null) { + wildcards.allow.setExact(MatchField.TCP_DST, this.tp_dst); + } else { + wildcards.allow.setExact(MatchField.UDP_DST, this.tp_dst); + } } } } @@ -331,9 +368,11 @@ public class FirewallRule implements Comparable<FirewallRule> { } } if (action == FirewallRule.FirewallAction.DENY) { - wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; + //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; + wildcards.drop.setExact(MatchField.ETH_TYPE, this.dl_type); } else { - wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE; + //wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE; + wildcards.allow.setExact(MatchField.ETH_TYPE, this.dl_type); } // all applicable checks passed @@ -382,18 +421,18 @@ public class FirewallRule implements Comparable<FirewallRule> { public int hashCode() { final int prime = 2521; int result = super.hashCode(); - result = prime * result + (int) dpid; - result = prime * result + in_port; - result = prime * result + (int) dl_src; - result = prime * result + (int) dl_dst; - result = prime * result + dl_type; - result = prime * result + nw_src_prefix; - result = prime * result + nw_src_maskbits; - result = prime * result + nw_dst_prefix; - result = prime * result + nw_dst_maskbits; - result = prime * result + nw_proto; - result = prime * result + tp_src; - result = prime * result + tp_dst; + result = prime * result + (int) dpid.getLong(); + result = prime * result + in_port.getPortNumber(); + result = prime * result + (int) dl_src.getLong(); + result = prime * result + (int) dl_dst.getLong(); + result = prime * result + dl_type.getValue(); + result = prime * result + nw_src_prefix_and_mask.getValue().getInt(); + result = prime * result + nw_src_prefix_and_mask.getMask().getInt(); + result = prime * result + nw_dst_prefix_and_mask.getValue().getInt(); + result = prime * result + nw_dst_prefix_and_mask.getMask().getInt(); + result = prime * result + nw_proto.getIpProtocolNumber(); + result = prime * result + tp_src.getPort(); + result = prime * result + tp_dst.getPort(); result = prime * result + action.ordinal(); result = prime * result + priority; result = prime * result + (new Boolean(wildcard_dpid)).hashCode(); diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java index 3180968d1dd1786ef183933bc8584a5b896b123d..42cb2727f79e3403d0b1ddd0d777468a07092627 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java @@ -19,14 +19,10 @@ package net.floodlightcontroller.firewall; import java.io.IOException; -import net.floodlightcontroller.packet.IPv4; -import net.floodlightcontroller.util.MACAddress; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import org.openflow.util.HexString; /** * Serialize a FirewallRule object @@ -42,18 +38,18 @@ public class FirewallRuleSerializer extends JsonSerializer<FirewallRule> { jGen.writeStartObject(); jGen.writeNumberField("ruleid", rule.ruleid); - jGen.writeStringField("dpid", HexString.toHexString(rule.dpid)); - jGen.writeNumberField("in_port", rule.in_port); - jGen.writeStringField("dl_src",String.valueOf(MACAddress.valueOf(rule.dl_src))); - jGen.writeStringField("dl_dst", String.valueOf(MACAddress.valueOf(rule.dl_dst))); - jGen.writeNumberField("dl_type", rule.dl_type); - jGen.writeStringField("nw_src_prefix", IPv4.fromIPv4Address(rule.nw_src_prefix)); - jGen.writeNumberField("nw_src_maskbits", rule.nw_src_maskbits); - jGen.writeStringField("nw_dst_prefix", IPv4.fromIPv4Address(rule.nw_dst_prefix)); - jGen.writeNumberField("nw_dst_maskbits", rule.nw_dst_maskbits); - jGen.writeNumberField("nw_proto", rule.nw_proto); - jGen.writeNumberField("tp_src", rule.tp_src); - jGen.writeNumberField("tp_dst", rule.tp_dst); + jGen.writeStringField("dpid", rule.dpid.toString()); + jGen.writeNumberField("in_port", rule.in_port.getPortNumber()); + jGen.writeStringField("dl_src", rule.dl_src.toString()); + jGen.writeStringField("dl_dst", rule.dl_dst.toString()); + jGen.writeNumberField("dl_type", rule.dl_type.getValue()); + jGen.writeStringField("nw_src_prefix", rule.nw_src_prefix_and_mask.getValue().toString()); + jGen.writeNumberField("nw_src_maskbits", rule.nw_src_prefix_and_mask.getMask().asCidrMaskLength()); + jGen.writeStringField("nw_dst_prefix", rule.nw_dst_prefix_and_mask.getValue().toString()); + jGen.writeNumberField("nw_dst_maskbits", rule.nw_dst_prefix_and_mask.getMask().asCidrMaskLength()); + jGen.writeNumberField("nw_proto", rule.nw_proto.getIpProtocolNumber()); + jGen.writeNumberField("tp_src", rule.tp_src.getPort()); + jGen.writeNumberField("tp_dst", rule.tp_dst.getPort()); jGen.writeBooleanField("wildcard_dpid", rule.wildcard_dpid); jGen.writeBooleanField("wildcard_in_port", rule.wildcard_in_port); jGen.writeBooleanField("wildcard_dl_src", rule.wildcard_dl_src); diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java index 7af219cc63f70879eda9cdd5ab7971b1a3111cea..27e40d3ffecebecc8b268125ee0441cf7ea8348c 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java @@ -25,7 +25,14 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.MappingJsonFactory; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.EthType; +import org.projectfloodlight.openflow.types.IPv4AddressWithMask; +import org.projectfloodlight.openflow.types.IpProtocol; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.TransportPort; import org.restlet.resource.Delete; import org.restlet.resource.Post; import org.restlet.resource.Get; @@ -33,7 +40,6 @@ import org.restlet.resource.ServerResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; public class FirewallRulesResource extends ServerResource { @@ -166,13 +172,13 @@ public class FirewallRulesResource extends ServerResource { tmp = jp.getText(); if (tmp.equalsIgnoreCase("-1") == false) { // user inputs hex format dpid - rule.dpid = HexString.toLong(tmp); + rule.dpid = DatapathId.of(tmp); rule.wildcard_dpid = false; } } else if (n == "src-inport") { - rule.in_port = Short.parseShort(jp.getText()); + rule.in_port = OFPort.of(Integer.parseInt(jp.getText())); rule.wildcard_in_port = false; } @@ -180,7 +186,7 @@ public class FirewallRulesResource extends ServerResource { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ANY") == false) { rule.wildcard_dl_src = false; - rule.dl_src = Ethernet.toLong(Ethernet.toMACAddress(tmp)); + rule.dl_src = MacAddress.of(tmp); } } @@ -188,7 +194,7 @@ public class FirewallRulesResource extends ServerResource { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ANY") == false) { rule.wildcard_dl_dst = false; - rule.dl_dst = Ethernet.toLong(Ethernet.toMACAddress(tmp)); + rule.dl_dst = MacAddress.of(tmp); } } @@ -196,11 +202,11 @@ public class FirewallRulesResource extends ServerResource { tmp = jp.getText(); if (tmp.equalsIgnoreCase("ARP")) { rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_ARP; + rule.dl_type = EthType.ARP; } if (tmp.equalsIgnoreCase("IPv4")) { rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_IPv4; + rule.dl_type = EthType.IPv4; } } @@ -209,10 +215,8 @@ public class FirewallRulesResource extends ServerResource { if (tmp.equalsIgnoreCase("ANY") == false) { rule.wildcard_nw_src = false; rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_IPv4; - int[] cidr = IPCIDRToPrefixBits(tmp); - rule.nw_src_prefix = cidr[0]; - rule.nw_src_maskbits = cidr[1]; + rule.dl_type = EthType.IPv4; + rule.nw_src_prefix_and_mask = IPv4AddressWithMask.of(tmp); } } @@ -221,10 +225,8 @@ public class FirewallRulesResource extends ServerResource { if (tmp.equalsIgnoreCase("ANY") == false) { rule.wildcard_nw_dst = false; rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_IPv4; - int[] cidr = IPCIDRToPrefixBits(tmp); - rule.nw_dst_prefix = cidr[0]; - rule.nw_dst_maskbits = cidr[1]; + rule.dl_type = EthType.IPv4; + rule.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(tmp); } } @@ -232,30 +234,30 @@ public class FirewallRulesResource extends ServerResource { tmp = jp.getText(); if (tmp.equalsIgnoreCase("TCP")) { rule.wildcard_nw_proto = false; - rule.nw_proto = IPv4.PROTOCOL_TCP; + rule.nw_proto = IpProtocol.TCP; rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_IPv4; + rule.dl_type = EthType.IPv4; } else if (tmp.equalsIgnoreCase("UDP")) { rule.wildcard_nw_proto = false; - rule.nw_proto = IPv4.PROTOCOL_UDP; + rule.nw_proto = IpProtocol.UDP; rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_IPv4; + rule.dl_type = EthType.IPv4; } else if (tmp.equalsIgnoreCase("ICMP")) { rule.wildcard_nw_proto = false; - rule.nw_proto = IPv4.PROTOCOL_ICMP; + rule.nw_proto = IpProtocol.ICMP; rule.wildcard_dl_type = false; - rule.dl_type = Ethernet.TYPE_IPv4; + rule.dl_type = EthType.IPv4; } } else if (n == "tp-src") { rule.wildcard_tp_src = false; - rule.tp_src = Short.parseShort(jp.getText()); + rule.tp_src = TransportPort.of(Integer.parseInt(jp.getText())); } else if (n == "tp-dst") { rule.wildcard_tp_dst = false; - rule.tp_dst = Short.parseShort(jp.getText()); + rule.tp_dst = TransportPort.of(Integer.parseInt(jp.getText())); } else if (n == "priority") { diff --git a/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java b/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java index d2aa2e5ff458b4fdef9c00bb4544e9851df3fe5c..114dc3eee332c005030152b69141873e1a7371b8 100644 --- a/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java +++ b/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java @@ -17,9 +17,9 @@ package net.floodlightcontroller.firewall; -import org.openflow.protocol.OFMatch; +import org.projectfloodlight.openflow.protocol.match.Match; public class RuleWildcardsPair { public FirewallRule rule; - public int wildcards = OFMatch.OFPFW_ALL; + public Match.Builder wildcards; } diff --git a/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java b/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java index db4cf7441a11de5931a7b9b2db4205a9d66c54e6..f6443c403e1de021319e84869b8f07f911e48f21 100644 --- a/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java +++ b/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java @@ -17,9 +17,12 @@ package net.floodlightcontroller.firewall; -import org.openflow.protocol.OFMatch; +import org.projectfloodlight.openflow.protocol.match.Match; + public class WildcardsPair { - public int allow = OFMatch.OFPFW_ALL; - public int drop = OFMatch.OFPFW_ALL; + //public int allow = OFMatch.OFPFW_ALL; + //public int drop = OFMatch.OFPFW_ALL; + public Match.Builder allow; + public Match.Builder drop; } diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java index 588e8bc3123336bf3fa7bab8a421e5ce17ff456c..40fc77bcf04734639005148fc7c98a81ea555f9a 100644 --- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java +++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java @@ -33,6 +33,7 @@ import net.floodlightcontroller.devicemanager.SwitchPort; import net.floodlightcontroller.core.annotations.LogMessageCategory; import net.floodlightcontroller.core.annotations.LogMessageDoc; import net.floodlightcontroller.core.annotations.LogMessageDocs; +import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; @@ -40,20 +41,30 @@ import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.packet.Ethernet; +import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.routing.ForwardingBase; import net.floodlightcontroller.routing.IRoutingDecision; import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.topology.ITopologyService; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.OFFlowModCommand; +import org.projectfloodlight.openflow.protocol.OFFlowModFlags; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.match.MatchField; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.OFVlanVidMatch; +import org.projectfloodlight.openflow.types.VlanVid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -161,24 +172,29 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { protected void doForwardFlow(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx, boolean requestFlowRemovedNotifn) { - OFMatch match = new OFMatch(); - match.loadFromPacket(pi.getPacketData(), pi.getInPort()); - + //OFMatch match = new OFMatch(); + //match.loadFromPacket(pi.getData(), pi.getInPort()); + //Match.Builder matchBuilder = sw.getOFFactory().buildMatch(); + Match match = pi.getMatch(); // Check if we have the location of the destination IDevice dstDevice = IDeviceService.fcStore. get(cntx, IDeviceService.CONTEXT_DST_DEVICE); + // DESTINATION DEVICE = KNOWN if (dstDevice != null) { IDevice srcDevice = IDeviceService.fcStore. get(cntx, IDeviceService.CONTEXT_SRC_DEVICE); - Long srcIsland = topology.getL2DomainId(sw.getId()); + DatapathId srcIsland = topology.getL2DomainId(sw.getId()); + // If we can't find the source device, that's no good if (srcDevice == null) { log.debug("No device entry found for source device"); return; } + + // If the source isn't connected to an OF island we control, then that's not good either if (srcIsland == null) { log.debug("No openflow island found for source {}/{}", sw.getStringId(), pi.getInPort()); @@ -186,24 +202,24 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { } // Validate that we have a destination known on the same island - // Validate that the source and destination are not on the same switchport + // Validate that the source and destination are not on the same switch port boolean on_same_island = false; boolean on_same_if = false; for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) { - long dstSwDpid = dstDap.getSwitchDPID(); - Long dstIsland = topology.getL2DomainId(dstSwDpid); + DatapathId dstSwDpid = dstDap.getSwitchDPID(); + DatapathId dstIsland = topology.getL2DomainId(dstSwDpid); if ((dstIsland != null) && dstIsland.equals(srcIsland)) { on_same_island = true; - if ((sw.getId() == dstSwDpid) && - (pi.getInPort() == dstDap.getPort())) { + if ((sw.getId().equals(dstSwDpid)) && + (pi.getInPort().equals(dstDap.getPort()))) { on_same_if = true; } break; } } + // If the two devices are not on the same L2 network, find out how to get to the destination via flooding if (!on_same_island) { - // Flood since we don't know the dst device if (log.isTraceEnabled()) { log.trace("No first hop island found for destination " + "device {}, Action = flooding", dstDevice); @@ -212,6 +228,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { return; } + // If the two devices are on the same switch port number, they should be able to communicate w/o further flows if (on_same_if) { if (log.isTraceEnabled()) { log.trace("Both source and destination are on the same " + @@ -237,9 +254,9 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { // srcCluster and dstCluster here cannot be null as // every switch will be at least in its own L2 domain. - Long srcCluster = + DatapathId srcCluster = topology.getL2DomainId(srcDap.getSwitchDPID()); - Long dstCluster = + DatapathId dstCluster = topology.getL2DomainId(dstDap.getSwitchDPID()); int srcVsDest = srcCluster.compareTo(dstCluster); @@ -247,9 +264,9 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { if (!srcDap.equals(dstDap)) { Route route = routingEngine.getRoute(srcDap.getSwitchDPID(), - (short)srcDap.getPort(), + srcDap.getPort(), dstDap.getSwitchDPID(), - (short)dstDap.getPort(), 0); //cookie = 0, i.e., default route + dstDap.getPort(), 0); //cookie = 0, i.e., default route if (route != null) { if (log.isTraceEnabled()) { log.trace("pushRoute match={} route={} " + @@ -262,7 +279,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { AppCookie.makeCookie(FORWARDING_APP_ID, 0); // if there is prior routing decision use wildcard - Integer wildcard_hints = null; + Match.Builder wildcard_hints; IRoutingDecision decision = null; if (cntx != null) { decision = IRoutingDecision.rtStore @@ -273,7 +290,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { wildcard_hints = decision.getWildcards(); } else { // L2 only wildcard if there is no prior route decision - wildcard_hints = ((Integer) sw + /*wildcard_hints = ((Integer) sw .getAttribute(IOFSwitch.PROP_FASTWILDCARDS)) .intValue() & ~OFMatch.OFPFW_IN_PORT @@ -281,12 +298,21 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_DL_DST & ~OFMatch.OFPFW_NW_SRC_MASK - & ~OFMatch.OFPFW_NW_DST_MASK; + & ~OFMatch.OFPFW_NW_DST_MASK;*/ + //TODO @Ryan does the use of NO_MASK here automatically assume isFullyWildcarded is true? + // dummy values set to not trigger isFullyWildcarded + wildcard_hints = sw.getOFFactory().buildMatch(); + wildcard_hints.setExact(MatchField.IN_PORT, OFPort.of(1)); + wildcard_hints.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(1)); + wildcard_hints.setExact(MatchField.ETH_SRC, MacAddress.BROADCAST); + wildcard_hints.setExact(MatchField.ETH_DST, MacAddress.BROADCAST); + wildcard_hints.setExact(MatchField.IPV4_SRC, IPv4Address.FULL_MASK); + wildcard_hints.setExact(MatchField.IPV4_DST, IPv4Address.FULL_MASK); } pushRoute(route, match, wildcard_hints, pi, sw.getId(), cookie, cntx, requestFlowRemovedNotifn, false, - OFFlowMod.OFPFC_ADD); + OFFlowModCommand.ADD); } } iSrcDaps++; @@ -297,8 +323,9 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { iDstDaps++; } } + // END DESTINATION DEVICE = KNOWN } else { - // Flood since we don't know the dst device + // DESTINATION DEVICE = UNKNOWN, thus flood to hopefully/eventually find out where the destination is doFlood(sw, pi, cntx); } } @@ -385,6 +412,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); l.add(IFloodlightProviderService.class); + l.add(IOFSwitchService.class); l.add(IDeviceService.class); l.add(IRoutingService.class); l.add(ITopologyService.class); @@ -412,6 +440,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule { public void init(FloodlightModuleContext context) throws FloodlightModuleException { super.init(); this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); + this.switchService = context.getServiceImpl(IOFSwitchService.class); this.deviceManager = context.getServiceImpl(IDeviceService.class); this.routingEngine = context.getServiceImpl(IRoutingService.class); this.topology = context.getServiceImpl(ITopologyService.class); diff --git a/src/main/java/net/floodlightcontroller/hub/Hub.java b/src/main/java/net/floodlightcontroller/hub/Hub.java index 4a3549ba47224cc0b8a7821798f589d61fbabb52..e683fa917443d2c7abe24a3b331f13ecbce0fbfb 100644 --- a/src/main/java/net/floodlightcontroller/hub/Hub.java +++ b/src/main/java/net/floodlightcontroller/hub/Hub.java @@ -17,7 +17,6 @@ package net.floodlightcontroller.hub; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -27,19 +26,20 @@ import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.LogicalOFMessageCategory; 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 org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; -import org.openflow.util.U16; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,34 +64,24 @@ public class Hub implements IFloodlightModule, IOFMessageListener { return Hub.class.getPackage().getName(); } + //TODO @Ryan this is a good example (my first try) at using the builders. Might be good reference later. public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { OFPacketIn pi = (OFPacketIn) msg; - OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.PACKET_OUT); - po.setBufferId(pi.getBufferId()) - .setInPort(pi.getInPort()); + OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); + pob.setBufferId(pi.getBufferId()).setInPort(pi.getInPort()); // set actions - OFActionOutput action = new OFActionOutput() - .setPort(OFPort.OFPP_FLOOD.getValue()); - po.setActions(Collections.singletonList((OFAction)action)); - po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); + OFActionOutput.Builder actionBuilder = sw.getOFFactory().actions().buildOutput(); + actionBuilder.setPort(OFPort.FLOOD); + pob.setActions(Collections.singletonList((OFAction) actionBuilder.build())); + // pob.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); @Ryan setting of lengths is taken care of now, I think // set data if is is included in the packetin - if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { - byte[] packetData = pi.getPacketData(); - po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH - + po.getActionsLength() + packetData.length)); - po.setPacketData(packetData); - } else { - po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH - + po.getActionsLength())); - } - try { - sw.write(po, cntx); - } catch (IOException e) { - log.error("Failure writing PacketOut", e); + if (pi.getBufferId() == OFBufferId.NO_BUFFER) { + byte[] packetData = pi.getData(); + pob.setData(packetData); } + sw.write(pob.build(), LogicalOFMessageCategory.MAIN); return Command.CONTINUE; } diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java index e4e109ca46fea5d8605109aea8f497c6300edcb6..5025d8d6981d8c5002477a0c754de4932fb0232a 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java @@ -18,7 +18,9 @@ package net.floodlightcontroller.linkdiscovery; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; public interface ILinkDiscovery { @@ -45,16 +47,16 @@ public interface ILinkDiscovery { } public class LDUpdate { - protected long src; - protected short srcPort; - protected long dst; - protected short dstPort; + protected DatapathId src; + protected OFPort srcPort; + protected DatapathId dst; + protected OFPort dstPort; protected SwitchType srcType; protected LinkType type; protected UpdateOperation operation; - public LDUpdate(long src, short srcPort, - long dst, short dstPort, + public LDUpdate(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort, ILinkDiscovery.LinkType type, UpdateOperation operation) { this.src = src; @@ -76,32 +78,32 @@ public interface ILinkDiscovery { } // For updtedSwitch(sw) - public LDUpdate(long switchId, SwitchType stype, UpdateOperation oper ){ + public LDUpdate(DatapathId switchId, SwitchType stype, UpdateOperation oper ){ this.operation = oper; this.src = switchId; this.srcType = stype; } // For port up or port down; and tunnel port added and removed. - public LDUpdate(long sw, short port, UpdateOperation operation) { + public LDUpdate(DatapathId sw, OFPort port, UpdateOperation operation) { this.src = sw; this.srcPort = port; this.operation = operation; } - public long getSrc() { + public DatapathId getSrc() { return src; } - public short getSrcPort() { + public OFPort getSrcPort() { return srcPort; } - public long getDst() { + public DatapathId getDst() { return dst; } - public short getDstPort() { + public OFPort getDstPort() { return dstPort; } @@ -127,20 +129,20 @@ public interface ILinkDiscovery { case LINK_REMOVED: case LINK_UPDATED: return "LDUpdate [operation=" + operation + - ", src=" + HexString.toHexString(src) - + ", srcPort=" + srcPort - + ", dst=" + HexString.toHexString(dst) - + ", dstPort=" + dstPort + ", src=" + src.toString() + + ", srcPort=" + srcPort.toString() + + ", dst=" + dst.toString() + + ", dstPort=" + dstPort.toString() + ", type=" + type + "]"; case PORT_DOWN: case PORT_UP: return "LDUpdate [operation=" + operation + - ", src=" + HexString.toHexString(src) - + ", srcPort=" + srcPort + "]"; + ", src=" + src.toString() + + ", srcPort=" + srcPort.toString() + "]"; case SWITCH_REMOVED: case SWITCH_UPDATED: return "LDUpdate [operation=" + operation + - ", src=" + HexString.toHexString(src) + "]"; + ", src=" + src.toString() + "]"; default: return "LDUpdate: Unknown update."; } diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java index 3773efd713b992755e093bd50dfdaf85317114a0..2bb53727917ffba3b4138bf3d06a9e56b79db1f2 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java @@ -20,7 +20,10 @@ package net.floodlightcontroller.linkdiscovery; import java.util.Map; import java.util.Set; -import org.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.routing.Link; @@ -32,7 +35,7 @@ public interface ILinkDiscoveryService extends IFloodlightService { /** * Returns if a given switchport is a tunnel endpoint or not */ - public boolean isTunnelPort(long sw, short port); + public boolean isTunnelPort(DatapathId sw, OFPort port); /** * Retrieves a map of all known link connections between OpenFlow switches @@ -59,7 +62,7 @@ public interface ILinkDiscoveryService extends IFloodlightService { * to switchport (sw, port). PacketOut does not contain actions. * PacketOut length includes the minimum length and data length. */ - public OFPacketOut generateLLDPMessage(long sw, short port, + public OFPacketOut generateLLDPMessage(DatapathId sw, OFPort port, boolean isStandard, boolean isReverse); @@ -67,7 +70,7 @@ public interface ILinkDiscoveryService extends IFloodlightService { * Returns an unmodifiable map from switch id to a set of all links with it * as an endpoint. */ - public Map<Long, Set<Link>> getSwitchLinks(); + public Map<DatapathId, Set<Link>> getSwitchLinks(); /** * Adds a listener to listen for ILinkDiscoveryService messages @@ -84,17 +87,17 @@ public interface ILinkDiscoveryService extends IFloodlightService { * Adds a switch port to suppress lldp set. LLDPs and BDDPs will not be sent * out, and if any are received on this port then they will be dropped. */ - public void AddToSuppressLLDPs(long sw, short port); + public void AddToSuppressLLDPs(DatapathId sw, OFPort port); /** * Removes a switch port from suppress lldp set */ - public void RemoveFromSuppressLLDPs(long sw, short port); + public void RemoveFromSuppressLLDPs(DatapathId sw, OFPort port); /** * Get the set of quarantined ports on a switch */ - public Set<Short> getQuarantinedPorts(long sw); + public Set<OFPort> getQuarantinedPorts(DatapathId sw); /** * Get the status of auto port fast feature. @@ -126,5 +129,5 @@ public interface ILinkDiscoveryService extends IFloodlightService { * ALL MAC addresses to the ignore list. This will cause a drop of * ALL packet ins. */ - public void addMACToIgnoreList(long mac, int ignoreBits); + public void addMACToIgnoreList(MacAddress mac, int ignoreBits); } diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java b/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java index 0230b3bbd31f8cb47581ff83f6b79f4632386560..6c2d7334e436cabe3f44eca1547d4f1425c3d440 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java @@ -15,15 +15,17 @@ package net.floodlightcontroller.linkdiscovery; +import java.util.Date; + import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType; import com.fasterxml.jackson.annotation.JsonIgnore; public class LinkInfo { - public LinkInfo(Long firstSeenTime, - Long lastLldpReceivedTime, - Long lastBddpReceivedTime) { + public LinkInfo(Date firstSeenTime, + Date lastLldpReceivedTime, + Date lastBddpReceivedTime) { super(); this.firstSeenTime = firstSeenTime; this.lastLldpReceivedTime = lastLldpReceivedTime; @@ -46,9 +48,9 @@ public class LinkInfo { this.lastBddpReceivedTime = fromLinkInfo.getMulticastValidTime(); } - protected Long firstSeenTime; - protected Long lastLldpReceivedTime; /* Standard LLLDP received time */ - protected Long lastBddpReceivedTime; /* Modified LLDP received time */ + protected Date firstSeenTime; + protected Date lastLldpReceivedTime; /* Standard LLLDP received time */ + protected Date lastBddpReceivedTime; /* Modified LLDP received time */ /** The port states stored here are topology's last knowledge of * the state of the port. This mostly mirrors the state @@ -60,27 +62,27 @@ public class LinkInfo { * requires the new state to be written to storage. */ - public Long getFirstSeenTime() { + public Date getFirstSeenTime() { return firstSeenTime; } - public void setFirstSeenTime(Long firstSeenTime) { + public void setFirstSeenTime(Date firstSeenTime) { this.firstSeenTime = firstSeenTime; } - public Long getUnicastValidTime() { + public Date getUnicastValidTime() { return lastLldpReceivedTime; } - public void setUnicastValidTime(Long unicastValidTime) { + public void setUnicastValidTime(Date unicastValidTime) { this.lastLldpReceivedTime = unicastValidTime; } - public Long getMulticastValidTime() { + public Date getMulticastValidTime() { return lastBddpReceivedTime; } - public void setMulticastValidTime(Long multicastValidTime) { + public void setMulticastValidTime(Date multicastValidTime) { this.lastBddpReceivedTime = multicastValidTime; } @@ -147,8 +149,8 @@ public class LinkInfo { */ @Override public String toString() { - return "LinkInfo [unicastValidTime=" + ((lastLldpReceivedTime == null) ? "null" : lastLldpReceivedTime) - + ", multicastValidTime=" + ((lastBddpReceivedTime == null) ? "null" : lastBddpReceivedTime) + return "LinkInfo [unicastValidTime=" + ((lastLldpReceivedTime == null) ? "null" : lastLldpReceivedTime.getTime()) + + ", multicastValidTime=" + ((lastBddpReceivedTime == null) ? "null" : lastBddpReceivedTime.getTime()) + "]"; } } diff --git a/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java b/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java index c9115eacb5c22c459cbaded572a64063125118c6..63f710e58748881ca2aabe1360e559448253fec8 100644 --- a/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java +++ b/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java @@ -21,7 +21,7 @@ package net.floodlightcontroller.packet; import java.nio.ByteBuffer; import java.util.Arrays; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.util.HexString; /** * @author Shudong Zhou (shudong.zhou@bigswitch.com) diff --git a/src/main/java/net/floodlightcontroller/packet/Ethernet.java b/src/main/java/net/floodlightcontroller/packet/Ethernet.java index 60887b3158e27a3d714927aab4f57b7085242164..d29b0859c64daff72d9d503c5bb866a422c5b67a 100644 --- a/src/main/java/net/floodlightcontroller/packet/Ethernet.java +++ b/src/main/java/net/floodlightcontroller/packet/Ethernet.java @@ -22,8 +22,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import net.floodlightcontroller.util.MACAddress; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.util.HexString; /** * @@ -49,8 +49,8 @@ public class Ethernet extends BasePacket { etherTypeClassMap.put(TYPE_BSN, BSN.class); } - protected MACAddress destinationMACAddress; - protected MACAddress sourceMACAddress; + protected MacAddress destinationMACAddress; + protected MacAddress sourceMACAddress; protected byte priorityCode; protected short vlanID; protected short etherType; @@ -68,13 +68,13 @@ public class Ethernet extends BasePacket { * @return the destination MAC as a byte array */ public byte[] getDestinationMACAddress() { - return destinationMACAddress.toBytes(); + return destinationMACAddress.getBytes(); } /** * @return the destination MAC */ - public MACAddress getDestinationMAC() { + public MacAddress getDestinationMAC() { return destinationMACAddress; } @@ -82,7 +82,7 @@ public class Ethernet extends BasePacket { * @param destinationMACAddress the destination MAC to set */ public Ethernet setDestinationMACAddress(byte[] destinationMACAddress) { - this.destinationMACAddress = MACAddress.valueOf(destinationMACAddress); + this.destinationMACAddress = MacAddress.of(destinationMACAddress); return this; } @@ -90,7 +90,7 @@ public class Ethernet extends BasePacket { * @param destinationMACAddress the destination MAC to set */ public Ethernet setDestinationMACAddress(String destinationMACAddress) { - this.destinationMACAddress = MACAddress.valueOf(destinationMACAddress); + this.destinationMACAddress = MacAddress.of(destinationMACAddress); return this; } @@ -98,13 +98,13 @@ public class Ethernet extends BasePacket { * @return the source MACAddress as a byte array */ public byte[] getSourceMACAddress() { - return sourceMACAddress.toBytes(); + return sourceMACAddress.getBytes(); } /** * @return the source MACAddress */ - public MACAddress getSourceMAC() { + public MacAddress getSourceMAC() { return sourceMACAddress; } @@ -112,7 +112,7 @@ public class Ethernet extends BasePacket { * @param sourceMACAddress the source MAC to set */ public Ethernet setSourceMACAddress(byte[] sourceMACAddress) { - this.sourceMACAddress = MACAddress.valueOf(sourceMACAddress); + this.sourceMACAddress = MacAddress.of(sourceMACAddress); return this; } @@ -120,7 +120,7 @@ public class Ethernet extends BasePacket { * @param sourceMACAddress the source MAC to set */ public Ethernet setSourceMACAddress(String sourceMACAddress) { - this.sourceMACAddress = MACAddress.valueOf(sourceMACAddress); + this.sourceMACAddress = MacAddress.of(sourceMACAddress); return this; } @@ -173,7 +173,7 @@ public class Ethernet extends BasePacket { * @return True if the Ethernet frame is broadcast, false otherwise */ public boolean isBroadcast() { - assert(destinationMACAddress.length() == 6); + assert(destinationMACAddress.getLength() == 6); return destinationMACAddress.isBroadcast(); } @@ -213,8 +213,8 @@ public class Ethernet extends BasePacket { } byte[] data = new byte[length]; ByteBuffer bb = ByteBuffer.wrap(data); - bb.put(destinationMACAddress.toBytes()); - bb.put(sourceMACAddress.toBytes()); + bb.put(destinationMACAddress.getBytes()); + bb.put(sourceMACAddress.getBytes()); if (vlanID != VLAN_UNTAGGED) { bb.putShort((short) 0x8100); bb.putShort((short) ((priorityCode << 13) | (vlanID & 0x0fff))); @@ -234,16 +234,16 @@ public class Ethernet extends BasePacket { return null; ByteBuffer bb = ByteBuffer.wrap(data, offset, length); if (this.destinationMACAddress == null) - this.destinationMACAddress = MACAddress.valueOf(new byte[6]); - byte[] dstAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH]; + this.destinationMACAddress = MacAddress.of(new byte[6]); + byte[] dstAddr = new byte[MacAddress.NONE.getLength()]; bb.get(dstAddr); - this.destinationMACAddress = MACAddress.valueOf(dstAddr); + this.destinationMACAddress = MacAddress.of(dstAddr); if (this.sourceMACAddress == null) - this.sourceMACAddress = MACAddress.valueOf(new byte[6]); - byte[] srcAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH]; + this.sourceMACAddress = MacAddress.of(new byte[6]); + byte[] srcAddr = new byte[MacAddress.NONE.getLength()]; bb.get(srcAddr); - this.sourceMACAddress = MACAddress.valueOf(srcAddr); + this.sourceMACAddress = MacAddress.of(srcAddr); short etherType = bb.getShort(); if (etherType == (short) 0x8100) { @@ -322,7 +322,7 @@ public class Ethernet extends BasePacket { * @return The macAddress as a byte array */ public static byte[] toMACAddress(String macAddress) { - return MACAddress.valueOf(macAddress).toBytes(); + return MacAddress.of(macAddress).getBytes(); } @@ -333,7 +333,7 @@ public class Ethernet extends BasePacket { * @return a long containing the mac address bytes */ public static long toLong(byte[] macAddress) { - return MACAddress.valueOf(macAddress).toLong(); + return MacAddress.of(macAddress).getLong(); } /** @@ -342,7 +342,7 @@ public class Ethernet extends BasePacket { * @return the bytes of the mac address */ public static byte[] toByteArray(long macAddress) { - return MACAddress.valueOf(macAddress).toBytes(); + return MacAddress.of(macAddress).getBytes(); } /* (non-Javadoc) diff --git a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java index cc70487eb8497e4330b59f679196450a57e5559d..0198d16a45863b9c89ce9b51aec59ddc4a787532 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java +++ b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java @@ -18,7 +18,7 @@ package net.floodlightcontroller.perfmon; import java.util.List; -import org.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFMessage; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IOFMessageListener; diff --git a/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java index 51641ccc7651f80c7aec121763a3b04a7273b7b8..c10bc93a67a665d270e520fcee7d0b0965335b11 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java @@ -22,7 +22,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFMessage; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IOFMessageListener; diff --git a/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java index 366721120e332de7eb700ed383b521c7afb1a116..9e754469d917481db367d2afb67e014866b28c1e 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java @@ -37,8 +37,8 @@ import net.floodlightcontroller.core.module.IFloodlightModule; import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.restserver.IRestApiService; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java b/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java index 0c3703c97f9b3f8f07002203a0a7946c776cf0e7..28ca79f843a5f4984ab25eb012e95141c062c2bb 100644 --- a/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java +++ b/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java @@ -20,48 +20,48 @@ import java.util.HashMap; import net.floodlightcontroller.routing.Link; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; public class BroadcastTree { - protected HashMap<Long, Link> links; - protected HashMap<Long, Integer> costs; + protected HashMap<DatapathId, Link> links; + protected HashMap<DatapathId, Integer> costs; public BroadcastTree() { - links = new HashMap<Long, Link>(); - costs = new HashMap<Long, Integer>(); + links = new HashMap<DatapathId, Link>(); + costs = new HashMap<DatapathId, Integer>(); } - public BroadcastTree(HashMap<Long, Link> links, HashMap<Long, Integer> costs) { + public BroadcastTree(HashMap<DatapathId, Link> links, HashMap<DatapathId, Integer> costs) { this.links = links; this.costs = costs; } - public Link getTreeLink(long node) { + public Link getTreeLink(DatapathId node) { return links.get(node); } - public int getCost(long node) { + public int getCost(DatapathId node) { if (costs.get(node) == null) return -1; return (costs.get(node)); } - public HashMap<Long, Link> getLinks() { + public HashMap<DatapathId, Link> getLinks() { return links; } - public void addTreeLink(long myNode, Link link) { + public void addTreeLink(DatapathId myNode, Link link) { links.put(myNode, link); } public String toString() { StringBuffer sb = new StringBuffer(); - for(long n: links.keySet()) { - sb.append("[" + HexString.toHexString(n) + ": cost=" + costs.get(n) + ", " + links.get(n) + "]"); + for(DatapathId n: links.keySet()) { + sb.append("[" + n.toString() + ": cost=" + costs.get(n) + ", " + links.get(n) + "]"); } return sb.toString(); } - public HashMap<Long, Integer> getCosts() { + public HashMap<DatapathId, Integer> getCosts() { return costs; } } diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java index 2ef42197bd8a3a6a42c1b76df0682e37db5bf10e..a3b22551433ab428e38a03f11881e57006412084 100644 --- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java +++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java @@ -32,6 +32,7 @@ import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.annotations.LogMessageCategory; import net.floodlightcontroller.core.annotations.LogMessageDoc; import net.floodlightcontroller.core.annotations.LogMessageDocs; +import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.devicemanager.IDeviceService; @@ -46,14 +47,26 @@ import net.floodlightcontroller.topology.NodePortTuple; import net.floodlightcontroller.util.OFMessageDamper; import net.floodlightcontroller.util.TimedCache; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.match.MatchField; +import org.projectfloodlight.openflow.protocol.match.MatchFields; +import org.projectfloodlight.openflow.protocol.OFFlowAdd; +import org.projectfloodlight.openflow.protocol.OFFlowModCommand; +import org.projectfloodlight.openflow.protocol.OFFlowModify; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFPacketQueue; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFUint64; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.U64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,6 +96,7 @@ public abstract class ForwardingBase protected IRoutingService routingEngine; protected ITopologyService topology; protected ICounterStoreService counterStore; + protected IOFSwitchService switchService; protected OFMessageDamper messageDamper; @@ -106,9 +120,9 @@ public abstract class ForwardingBase new Comparator<SwitchPort>() { @Override public int compare(SwitchPort d1, SwitchPort d2) { - Long d1ClusterId = + DatapathId d1ClusterId = topology.getL2DomainId(d1.getSwitchDPID()); - Long d2ClusterId = + DatapathId d2ClusterId = topology.getL2DomainId(d2.getSwitchDPID()); return d1ClusterId.compareTo(d2ClusterId); } @@ -204,40 +218,35 @@ public abstract class ForwardingBase "flow modification to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) }) - public boolean pushRoute(Route route, OFMatch match, - Integer wildcard_hints, + public boolean pushRoute(Route route, Match match, + Match.Builder wildcard_hints, OFPacketIn pi, - long pinSwitch, + DatapathId pinSwitch, long cookie, FloodlightContext cntx, boolean reqeustFlowRemovedNotifn, boolean doFlush, - short flowModCommand) { + OFFlowModCommand flowModCommand) { boolean srcSwitchIncluded = false; - OFFlowMod fm = - (OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD); - OFActionOutput action = new OFActionOutput(); - action.setMaxLength((short)0xffff); + OFFlowAdd.Builder fmb = switchService.getSwitch(pinSwitch).getOFFactory().buildFlowAdd(); + OFActionOutput.Builder actionOutputBuilder = switchService.getSwitch(pinSwitch).getOFFactory().actions().buildOutput(); + actionOutputBuilder.setMaxLen((int) 0xffffffff); List<OFAction> actions = new ArrayList<OFAction>(); - actions.add(action); - - fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT) - .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setCookie(cookie) - .setCommand(flowModCommand) - .setMatch(match) - .setActions(actions) - .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH); - + actions.add(actionOutputBuilder.build()); + + fmb.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT) + .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT) + .setBufferId(OFBufferId.NO_BUFFER) + .setCookie(U64.of(cookie)) + .setMatch(match) + .setActions(actions); List<NodePortTuple> switchPortList = route.getPath(); - for (int indx = switchPortList.size()-1; indx > 0; indx -= 2) { + for (int indx = switchPortList.size() - 1; indx > 0; indx -= 2) { // indx and indx-1 will always have the same switch DPID. - long switchDPID = switchPortList.get(indx).getNodeId(); - IOFSwitch sw = floodlightProvider.getSwitch(switchDPID); + DatapathId switchDPID = switchPortList.get(indx).getNodeId(); + IOFSwitch sw = switchService.getSwitch(switchDPID); if (sw == null) { if (log.isWarnEnabled()) { log.warn("Unable to push route, switch at DPID {} " + @@ -247,26 +256,29 @@ public abstract class ForwardingBase } // set the match. - fm.setMatch(wildcard(match, sw, wildcard_hints)); + fmb.setMatch(wildcard(match, sw, wildcard_hints)); // set buffer id if it is the source switch - if (1 == indx) { + // this only appears to set wildcards, which I think are not necessary + /*if (1 == indx) { // Set the flag to request flow-mod removal notifications only for the // source switch. The removal message is used to maintain the flow // cache. Don't set the flag for ARP messages - TODO generalize check if ((reqeustFlowRemovedNotifn) - && (match.getDataLayerType() != Ethernet.TYPE_ARP)) { - /**with new flow cache design, we don't need the flow removal message from switch anymore - fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM); - */ - match.setWildcards(fm.getMatch().getWildcards()); + && (match.get(MatchField.ARP_OP).getOpcode() != Ethernet.TYPE_ARP)) { + //with new flow cache design, we don't need the flow removal message from switch anymore + //fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM); + // + match.setWildcards(fmb.getMatch().getWildcards()); } - } + }*/ - short outPort = switchPortList.get(indx).getPortId(); - short inPort = switchPortList.get(indx-1).getPortId(); + OFPort outPort = switchPortList.get(indx).getPortId(); + OFPort inPort = switchPortList.get(indx-1).getPortId(); // set input and output ports on the switch - fm.getMatch().setInputPort(inPort); + Match m = fmb.getMatch(); + m. + .setInputPort(inPort); ((OFActionOutput)fm.getActions().get(0)).setPort(outPort); try { @@ -286,7 +298,7 @@ public abstract class ForwardingBase } // Push the packet out the source switch - if (sw.getId() == pinSwitch) { + if (sw.getId().equals(pinSwitch)) { // TODO: Instead of doing a packetOut here we could also // send a flowMod with bufferId set.... pushPacket(sw, pi, false, outPort, cntx); @@ -306,13 +318,13 @@ public abstract class ForwardingBase return srcSwitchIncluded; } - protected OFMatch wildcard(OFMatch match, IOFSwitch sw, + /*protected Match wildcard(Match match, IOFSwitch sw, Integer wildcard_hints) { if (wildcard_hints != null) { return match.clone().setWildcards(wildcard_hints.intValue()); } return match.clone(); - } + }*/ /** * Pushes a packet-out to a switch. If bufferId != BUFFER_ID_NONE we @@ -357,7 +369,7 @@ public abstract class ForwardingBase */ protected void pushPacket(IOFSwitch sw, OFPacketIn pi, boolean useBufferId, - short outport, FloodlightContext cntx) { + OFPort outport, FloodlightContext cntx) { if (pi == null) { return; @@ -381,37 +393,35 @@ public abstract class ForwardingBase new Object[] {sw, pi}); } - OFPacketOut po = - (OFPacketOut) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.PACKET_OUT); + //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); + OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); // set actions List<OFAction> actions = new ArrayList<OFAction>(); - actions.add(new OFActionOutput(outport, (short) 0xffff)); + //actions.add(new OFActionOutput(outport, (short) 0xffff)); + actions.add(sw.getOFFactory().actions().output(outport, (int) 0xffffffff)); - po.setActions(actions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); - short poLength = - (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); + pob.setActions(actions); + //.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); + //short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); if (useBufferId) { - po.setBufferId(pi.getBufferId()); + pob.setBufferId(pi.getBufferId()); } else { - po.setBufferId(OFPacketOut.BUFFER_ID_NONE); + pob.setBufferId(OFBufferId.NO_BUFFER); } - if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) { - byte[] packetData = pi.getPacketData(); - poLength += packetData.length; - po.setPacketData(packetData); + if (pob.getBufferId() == OFBufferId.NO_BUFFER) { + //poLength += packetData.length; + pob.setData(pi.getData()); } - po.setInPort(pi.getInPort()); - po.setLength(poLength); + pob.setInPort(pi.getInPort()); + //po.setLength(poLength); try { - counterStore.updatePktOutFMCounterStoreLocal(sw, po); - messageDamper.write(sw, po, cntx); + counterStore.updatePktOutFMCounterStoreLocal(sw, pob.build()); + messageDamper.write(sw, pob.build(), cntx); } catch (IOException e) { log.error("Failure writing packet out", e); } @@ -429,46 +439,43 @@ public abstract class ForwardingBase */ public void packetOutMultiPort(byte[] packetData, IOFSwitch sw, - short inPort, - Set<Integer> outPorts, + OFPort inPort, + Set<OFPort> outPorts, FloodlightContext cntx) { //setting actions List<OFAction> actions = new ArrayList<OFAction>(); - Iterator<Integer> j = outPorts.iterator(); + Iterator<OFPort> j = outPorts.iterator(); while (j.hasNext()) { - actions.add(new OFActionOutput(j.next().shortValue(), - (short) 0)); + //actions.add(new OFActionOutput(j.next().shortValue(), (short) 0)); + actions.add(sw.getOFFactory().actions().output(j.next(), 0)); } - OFPacketOut po = - (OFPacketOut) floodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_OUT); - po.setActions(actions); - po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * - outPorts.size())); + //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); + OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); + pob.setActions(actions); + //po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * outPorts.size())); // set buffer-id to BUFFER_ID_NONE, and set in-port to OFPP_NONE - po.setBufferId(OFPacketOut.BUFFER_ID_NONE); - po.setInPort(inPort); + pob.setBufferId(OFBufferId.NO_BUFFER); + pob.setInPort(inPort); // data (note buffer_id is always BUFFER_ID_NONE) and length - short poLength = (short)(po.getActionsLength() + - OFPacketOut.MINIMUM_LENGTH); - poLength += packetData.length; - po.setPacketData(packetData); - po.setLength(poLength); + //short poLength = (short)(po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH); + //poLength += packetData.length; + pob.setData(packetData); + //po.setLength(poLength); try { - counterStore.updatePktOutFMCounterStoreLocal(sw, po); + counterStore.updatePktOutFMCounterStoreLocal(sw, pob.build()); if (log.isTraceEnabled()) { log.trace("write broadcast packet on switch-id={} " + "interfaces={} packet-out={}", - new Object[] {sw.getId(), outPorts, po}); + new Object[] {sw.getId(), outPorts, pob.build()}); } - messageDamper.write(sw, po, cntx); + messageDamper.write(sw, pob.build(), cntx); } catch (IOException e) { log.error("Failure writing packet out", e); @@ -482,10 +489,10 @@ public abstract class ForwardingBase */ public void packetOutMultiPort(OFPacketIn pi, IOFSwitch sw, - short inPort, - Set<Integer> outPorts, + OFPort inPort, + Set<OFPort> outPorts, FloodlightContext cntx) { - packetOutMultiPort(pi.getPacketData(), sw, inPort, outPorts, cntx); + packetOutMultiPort(pi.getData(), sw, inPort, outPorts, cntx); } /** @@ -495,8 +502,8 @@ public abstract class ForwardingBase */ public void packetOutMultiPort(IPacket packet, IOFSwitch sw, - short inPort, - Set<Integer> outPorts, + OFPort inPort, + Set<OFPort> outPorts, FloodlightContext cntx) { packetOutMultiPort(packet.serialize(), sw, inPort, outPorts, cntx); } @@ -515,8 +522,8 @@ public abstract class ForwardingBase IFloodlightProviderService.CONTEXT_PI_PAYLOAD); Long broadcastHash; - broadcastHash = topology.getL2DomainId(sw.getId()) * prime1 + - pi.getInPort() * prime2 + eth.hashCode(); + broadcastHash = topology.getL2DomainId(sw.getId()).getLong() * prime1 + + pi.getInPort().getPortNumber() * prime2 + eth.hashCode(); if (broadcastCache.update(broadcastHash)) { sw.updateBroadcastCache(broadcastHash, pi.getInPort()); return true; @@ -535,7 +542,7 @@ public abstract class ForwardingBase Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - long hash = pi.getInPort() * prime2 + eth.hashCode(); + long hash = pi.getInPort().getPortNumber() * prime2 + eth.hashCode(); // some FORWARD_OR_FLOOD packets are unicast with unknown destination mac return sw.updateBroadcastCache(hash, pi.getInPort()); @@ -549,53 +556,43 @@ public abstract class ForwardingBase recommendation=LogMessageDoc.CHECK_SWITCH) }) public static boolean - blockHost(IFloodlightProviderService floodlightProvider, - SwitchPort sw_tup, long host_mac, + blockHost(IOFSwitchService switchService, + SwitchPort sw_tup, MacAddress host_mac, short hardTimeout, long cookie) { if (sw_tup == null) { return false; } - IOFSwitch sw = - floodlightProvider.getSwitch(sw_tup.getSwitchDPID()); + IOFSwitch sw = switchService.getSwitch(sw_tup.getSwitchDPID()); if (sw == null) return false; - int inputPort = sw_tup.getPort(); + OFPort inputPort = sw_tup.getPort(); log.debug("blockHost sw={} port={} mac={}", - new Object[] { sw, sw_tup.getPort(), Long.valueOf(host_mac) }); + new Object[] { sw, sw_tup.getPort(), host_mac.getLong() }); // Create flow-mod based on packet-in and src-switch - OFFlowMod fm = - (OFFlowMod) floodlightProvider.getOFMessageFactory() - .getMessage(OFType.FLOW_MOD); - OFMatch match = new OFMatch(); + OFFlowMod.Builder fmb = switchService.getSwitch(sw_tup.getSwitchDPID()).getOFFactory().buildFlowAdd(); + Match.Builder mb = switchService.getSwitch(sw_tup.getSwitchDPID()).getOFFactory().buildMatch(); List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to // drop - match.setInputPort((short)inputPort); - if (host_mac != -1L) { - match.setDataLayerSource(Ethernet.toByteArray(host_mac)) - .setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC - & ~OFMatch.OFPFW_IN_PORT); - } else { + mb.setExact(MatchField.IN_PORT, inputPort); + if (host_mac.getLong() != -1L) { + //match.setDataLayerSource(Ethernet.toByteArray(host_mac)).setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_IN_PORT); + mb.setExact(MatchField.ETH_SRC, host_mac); + } /*else { match.setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_IN_PORT); - } - fm.setCookie(cookie) + }*/ + fmb.setCookie(U64.of(cookie)) .setHardTimeout(hardTimeout) .setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setMatch(match) - .setActions(actions) - .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH); - - try { - log.debug("write drop flow-mod sw={} match={} flow-mod={}", - new Object[] { sw, match, fm }); - // TODO: can't use the message damper sine this method is static - sw.write(fm, null); - } catch (IOException e) { - log.error("Failure writing deny flow mod", e); - return false; - } + .setBufferId(OFBufferId.NO_BUFFER) + .setMatch(mb.build()) + .setActions(actions); + + log.debug("write drop flow-mod sw={} match={} flow-mod={}", + new Object[] { sw, mb.build(), fmb.build() }); + // TODO: can't use the message damper sine this method is static + sw.write(fmb.build(), null); return true; } diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java index ab09375486b9f61b2cfa98b83a5e9eeb483bd20b..9c7a285970819db2cd48ebe92554ce7dc6d37fe3 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java @@ -19,6 +19,8 @@ package net.floodlightcontroller.routing; import java.util.List; +import org.projectfloodlight.openflow.protocol.match.Match; + import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.FloodlightContextStore; import net.floodlightcontroller.devicemanager.IDevice; @@ -57,8 +59,8 @@ public interface IRoutingDecision { public void addDestinationDevice(IDevice d); public List<SwitchPort> getMulticastInterfaces(); public void setMulticastInterfaces(List<SwitchPort> lspt); - public Integer getWildcards(); - public void setWildcards(Integer wildcards); + public Match.Builder getWildcards(); + public void setWildcards(Match.Builder wildcards); public short getHardTimeout(); public void setHardTimeout(short hardTimeout); } diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java index a3d77a83ba6309c02c6f99c19d2523eab2ecfa3b..6cff6f533a75e0a0b03cdab7a27c83fc61e00696 100644 --- a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java +++ b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java @@ -19,6 +19,9 @@ package net.floodlightcontroller.routing; import java.util.ArrayList; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; + import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.routing.Route; @@ -33,7 +36,7 @@ public interface IRoutingService extends IFloodlightService { * @param dst Destination switch DPID. * @param cookie cookie (usage determined by implementation; ignored by topology instance now). */ - public Route getRoute(long src, long dst, long cookie); + public Route getRoute(DatapathId src, DatapathId dst, long cookie); /** * Provides a route between src and dst, with option to allow or @@ -43,7 +46,7 @@ public interface IRoutingService extends IFloodlightService { * @param cookie cookie (usage determined by implementation; ignored by topology instance now). * @param tunnelEnabled boolean option. */ - public Route getRoute(long src, long dst, long cookie, boolean tunnelEnabled); + public Route getRoute(DatapathId src, DatapathId dst, long cookie, boolean tunnelEnabled); /** * Provides a route between srcPort on src and dstPort on dst. @@ -53,8 +56,8 @@ public interface IRoutingService extends IFloodlightService { * @param dstPort dstPort on Destination switch. * @param cookie cookie (usage determined by implementation; ignored by topology instance now). */ - public Route getRoute(long srcId, short srcPort, - long dstId, short dstPort, long cookie); + public Route getRoute(DatapathId srcId, OFPort srcPort, + DatapathId dstId, OFPort dstPort, long cookie); /** * Provides a route between srcPort on src and dstPort on dst. @@ -65,21 +68,21 @@ public interface IRoutingService extends IFloodlightService { * @param cookie cookie (usage determined by implementation; ignored by topology instance now). * @param tunnelEnabled boolean option. */ - public Route getRoute(long srcId, short srcPort, - long dstId, short dstPort, long cookie, + public Route getRoute(DatapathId srcId, OFPort srcPort, + DatapathId dstId, OFPort dstPort, long cookie, boolean tunnelEnabled); /** return all routes, if available */ - public ArrayList<Route> getRoutes(long longSrcDpid, long longDstDpid, boolean tunnelEnabled); + public ArrayList<Route> getRoutes(DatapathId longSrcDpid, DatapathId longDstDpid, boolean tunnelEnabled); /** Check if a route exists between src and dst, including tunnel links * in the path. */ - public boolean routeExists(long src, long dst); + public boolean routeExists(DatapathId src, DatapathId dst); /** Check if a route exists between src and dst, with option to have * or not have tunnels as part of the path. */ - public boolean routeExists(long src, long dst, boolean tunnelEnabled); + public boolean routeExists(DatapathId src, DatapathId dst, boolean tunnelEnabled); } diff --git a/src/main/java/net/floodlightcontroller/routing/Link.java b/src/main/java/net/floodlightcontroller/routing/Link.java index 561ae04c09ba4b4d3849763da46796dff4c03f95..a2f125f5a5b2cd73c9ce6bfaa65e4b56e87d6ff6 100755 --- a/src/main/java/net/floodlightcontroller/routing/Link.java +++ b/src/main/java/net/floodlightcontroller/routing/Link.java @@ -18,34 +18,28 @@ package net.floodlightcontroller.routing; import com.fasterxml.jackson.annotation.JsonProperty; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; public class Link implements Comparable<Link> { @JsonProperty("src-switch") - private long src; + private DatapathId src; @JsonProperty("src-port") - private short srcPort; + private OFPort srcPort; @JsonProperty("dst-switch") - private long dst; + private DatapathId dst; @JsonProperty("dst-port") - private short dstPort; + private OFPort dstPort; - public Link(long srcId, short srcPort, long dstId, short dstPort) { + public Link(DatapathId srcId, OFPort srcPort, DatapathId dstId, OFPort dstPort) { this.src = srcId; this.srcPort = srcPort; this.dst = dstId; this.dstPort = dstPort; } - // Convenience method - public Link(long srcId, int srcPort, long dstId, int dstPort) { - this.src = srcId; - this.srcPort = (short) srcPort; - this.dst = dstId; - this.dstPort = (short) dstPort; - } - /* * Do not use this constructor. Used primarily for JSON * Serialization/Deserialization @@ -54,35 +48,35 @@ public class Link implements Comparable<Link> { super(); } - public long getSrc() { + public DatapathId getSrc() { return src; } - public short getSrcPort() { + public OFPort getSrcPort() { return srcPort; } - public long getDst() { + public DatapathId getDst() { return dst; } - public short getDstPort() { + public OFPort getDstPort() { return dstPort; } - public void setSrc(long src) { + public void setSrc(DatapathId src) { this.src = src; } - public void setSrcPort(short srcPort) { + public void setSrcPort(OFPort srcPort) { this.srcPort = srcPort; } - public void setDst(long dst) { + public void setDst(DatapathId dst) { this.dst = dst; } - public void setDstPort(short dstPort) { + public void setDstPort(OFPort dstPort) { this.dstPort = dstPort; } @@ -90,10 +84,10 @@ public class Link implements Comparable<Link> { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + (int) (dst ^ (dst >>> 32)); - result = prime * result + dstPort; - result = prime * result + (int) (src ^ (src >>> 32)); - result = prime * result + srcPort; + result = prime * result + (int) (dst.getLong() ^ (dst.getLong() >>> 32)); + result = prime * result + dstPort.getPortNumber(); + result = prime * result + (int) (src.getLong() ^ (src.getLong() >>> 32)); + result = prime * result + srcPort.getPortNumber(); return result; } @@ -120,35 +114,36 @@ public class Link implements Comparable<Link> { @Override public String toString() { - return "Link [src=" + HexString.toHexString(this.src) + return "Link [src=" + this.src.toString() + " outPort=" - + (srcPort & 0xffff) - + ", dst=" + HexString.toHexString(this.dst) + + srcPort.toString() + + ", dst=" + this.dst.toString() + ", inPort=" - + (dstPort & 0xffff) + + dstPort.toString() + "]"; } + //TODO @Ryan there was some short 0xFFFF bitmasking here when ports were shorts. I don't get what that did other than just allow all bits of the short (16), so I just stringified the whole thing public String toKeyString() { - return (HexString.toHexString(this.src) + "|" + - (this.srcPort & 0xffff) + "|" + - HexString.toHexString(this.dst) + "|" + - (this.dstPort & 0xffff) ); + return (this.src.toString() + "|" + + this.srcPort.toString() + "|" + + this.dst.toString() + "|" + + this.dstPort.toString()); } @Override public int compareTo(Link a) { // compare link based on natural ordering - src id, src port, dst id, dst port if (this.getSrc() != a.getSrc()) - return (int) (this.getSrc() - a.getSrc()); + return (int) (this.getSrc().getLong() - a.getSrc().getLong()); if (this.getSrcPort() != a.getSrcPort()) - return (int) (this.getSrc() - a.getSrc()); + return (int) (this.getSrc().getLong() - a.getSrc().getLong()); if (this.getDst() != a.getDst()) - return (int) (this.getDst() - a.getDst()); + return (int) (this.getDst().getLong() - a.getDst().getLong()); - return this.getDstPort() - a.getDstPort(); + return this.getDstPort().getPortNumber() - a.getDstPort().getPortNumber(); } } diff --git a/src/main/java/net/floodlightcontroller/routing/Route.java b/src/main/java/net/floodlightcontroller/routing/Route.java index da00d50b7b82a3d3498b1523543a8558abbd579a..f41a9aaf1e159249e4eb831da30cf80abe993ad5 100755 --- a/src/main/java/net/floodlightcontroller/routing/Route.java +++ b/src/main/java/net/floodlightcontroller/routing/Route.java @@ -20,6 +20,8 @@ package net.floodlightcontroller.routing; import java.util.ArrayList; import java.util.List; +import org.projectfloodlight.openflow.types.DatapathId; + import net.floodlightcontroller.topology.NodePortTuple; /** @@ -39,7 +41,7 @@ public class Route implements Comparable<Route> { this.routeCount = 0; // useful if multipath routing available } - public Route(Long src, Long dst) { + public Route(DatapathId src, DatapathId dst) { super(); this.id = new RouteId(src, dst); this.switchPorts = new ArrayList<NodePortTuple>(); diff --git a/src/main/java/net/floodlightcontroller/routing/RouteId.java b/src/main/java/net/floodlightcontroller/routing/RouteId.java index 511db735969aa849d619783cdd88229d1922b27a..bd80f4d2c6727ab238ff18566896db16aae8223e 100755 --- a/src/main/java/net/floodlightcontroller/routing/RouteId.java +++ b/src/main/java/net/floodlightcontroller/routing/RouteId.java @@ -17,7 +17,7 @@ package net.floodlightcontroller.routing; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; /** * Stores the endpoints of a route, in this case datapath ids @@ -25,37 +25,37 @@ import org.openflow.util.HexString; * @author David Erickson (daviderickson@cs.stanford.edu) */ public class RouteId implements Cloneable, Comparable<RouteId> { - protected Long src; - protected Long dst; + protected DatapathId src; + protected DatapathId dst; protected long cookie; - public RouteId(Long src, Long dst) { + public RouteId(DatapathId src, DatapathId dst) { super(); this.src = src; this.dst = dst; this.cookie = 0; } - public RouteId(Long src, Long dst, long cookie) { + public RouteId(DatapathId src, DatapathId dst, long cookie) { super(); this.src = src; this.dst = dst; this.cookie = cookie; } - public Long getSrc() { + public DatapathId getSrc() { return src; } - public void setSrc(Long src) { + public void setSrc(DatapathId src) { this.src = src; } - public Long getDst() { + public DatapathId getDst() { return dst; } - public void setDst(Long dst) { + public void setDst(DatapathId dst) { this.dst = dst; } @@ -103,8 +103,8 @@ public class RouteId implements Cloneable, Comparable<RouteId> { @Override public String toString() { - return "RouteId [src=" + HexString.toHexString(this.src) + " dst=" - + HexString.toHexString(this.dst) + "]"; + return "RouteId [src=" + this.src.toString() + " dst=" + + this.dst.toString() + "]"; } @Override diff --git a/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java index aa4b3dde823ab75a38671e53767294d1964012f3..2d487f409ca01c9f7d0cbe859521be2b9dcd0a29 100644 --- a/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java +++ b/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java @@ -20,6 +20,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; + import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.devicemanager.IDevice; import net.floodlightcontroller.devicemanager.SwitchPort; @@ -28,15 +32,15 @@ import net.floodlightcontroller.devicemanager.SwitchPort; public class RoutingDecision implements IRoutingDecision { protected RoutingAction action; - protected Integer wildcards; + protected Match.Builder wildcards; protected short hardTimeout; protected SwitchPort srcPort; protected IDevice srcDevice; protected List<IDevice> destDevices; protected List<SwitchPort> broadcastIntertfaces; - public RoutingDecision(long swDipd, - short inPort, + public RoutingDecision(DatapathId swDipd, + OFPort inPort, IDevice srcDevice, RoutingAction action) { this.srcPort = new SwitchPort(swDipd, inPort); @@ -93,12 +97,12 @@ public class RoutingDecision implements IRoutingDecision { } @Override - public Integer getWildcards() { + public Match.Builder getWildcards() { return this.wildcards; } @Override - public void setWildcards(Integer wildcards) { + public void setWildcards(Match.Builder wildcards) { this.wildcards = wildcards; } @@ -120,6 +124,6 @@ public class RoutingDecision implements IRoutingDecision { public String toString() { return "action " + action + " wildcard " + - ((wildcards == null) ? null : "0x"+Integer.toHexString(wildcards.intValue())); + ((wildcards == null) ? null : wildcards.toString()); } } diff --git a/src/main/java/net/floodlightcontroller/topology/Cluster.java b/src/main/java/net/floodlightcontroller/topology/Cluster.java index e4ea23b8c97673f1d764b58211dd54f71f07b77c..914740f10246698c95c7cf0085cb09465c79a709 100644 --- a/src/main/java/net/floodlightcontroller/topology/Cluster.java +++ b/src/main/java/net/floodlightcontroller/topology/Cluster.java @@ -23,37 +23,37 @@ import java.util.Set; import net.floodlightcontroller.routing.Link; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; public class Cluster { - protected long id; // the lowest id of the nodes - protected Map<Long, Set<Link>> links; // set of links connected to a node. + protected DatapathId id; // the lowest id of the nodes + protected Map<DatapathId, Set<Link>> links; // set of links connected to a node. public Cluster() { - id = Long.MAX_VALUE; - links = new HashMap<Long, Set<Link>>(); + id = DatapathId.NONE; + links = new HashMap<DatapathId, Set<Link>>(); } - public long getId() { + public DatapathId getId() { return id; } - public void setId(long id) { + public void setId(DatapathId id) { this.id = id; } - public Map<Long, Set<Link>> getLinks() { + public Map<DatapathId, Set<Link>> getLinks() { return links; } - public Set<Long> getNodes() { + public Set<DatapathId> getNodes() { return links.keySet(); } - void add(long n) { + void add(DatapathId n) { if (links.containsKey(n) == false) { links.put(n, new HashSet<Link>()); - if (n < id) id = n; + if (n.getLong() < id.getLong()) id = n; } } @@ -67,7 +67,7 @@ public class Cluster { @Override public int hashCode() { - return (int) (id + id >>>32); + return (int) (id.getLong() + id.getLong() >>>32); } @Override @@ -84,6 +84,6 @@ public class Cluster { } public String toString() { - return "[Cluster id=" + HexString.toHexString(id) + ", " + links.keySet() + "]"; + return "[Cluster id=" + id.toString() + ", " + links.keySet() + "]"; } } diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java index d518b80d21320095b9baaa3f5223768c414a414a..d6bd177550852501cded815cc2132abc9dc868b0 100644 --- a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java +++ b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java @@ -19,192 +19,195 @@ package net.floodlightcontroller.topology; import java.util.Date; import java.util.Set; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; + import net.floodlightcontroller.core.module.IFloodlightService; public interface ITopologyService extends IFloodlightService { - public void addListener(ITopologyListener listener); - - public Date getLastUpdateTime(); - - /** - * Query to determine if devices must be learned on a given switch port. - */ - public boolean isAttachmentPointPort(long switchid, short port); - public boolean isAttachmentPointPort(long switchid, short port, - boolean tunnelEnabled); - - public long getOpenflowDomainId(long switchId); - public long getOpenflowDomainId(long switchId, boolean tunnelEnabled); - - /** - * Returns the identifier of the L2 domain of a given switch. - * @param switchId The DPID of the switch in long form - * @return The DPID of the switch that is the key for the cluster - */ - public long getL2DomainId(long switchId); - public long getL2DomainId(long switchId, boolean tunnelEnabled); - - /** - * Queries whether two switches are in the same cluster. - * @param switch1 - * @param switch2 - * @return true if the switches are in the same cluster - */ - public boolean inSameOpenflowDomain(long switch1, long switch2); - public boolean inSameOpenflowDomain(long switch1, long switch2, - boolean tunnelEnabled); - - public Set<Long> getSwitchesInOpenflowDomain(long switchDPID); - public Set<Long> getSwitchesInOpenflowDomain(long switchDPID, - boolean tunnelEnabled); - - /** - * Queries whether two switches are in the same island. - * Currently, island and cluster are the same. In future, - * islands could be different than clusters. - * @param switch1 - * @param switch2 - * @return True of they are in the same island, false otherwise - */ - public boolean inSameL2Domain(long switch1, long switch2); - public boolean inSameL2Domain(long switch1, long switch2, - boolean tunnelEnabled); - - public boolean isBroadcastDomainPort(long sw, short port); - public boolean isBroadcastDomainPort(long sw, short port, - boolean tunnelEnabled); - - - public boolean isAllowed(long sw, short portId); - public boolean isAllowed(long sw, short portId, boolean tunnelEnabled); - - /** - * Indicates if an attachment point on the new switch port is consistent - * with the attachment point on the old switch port or not. - */ - public boolean isConsistent(long oldSw, short oldPort, - long newSw, short newPort); - public boolean isConsistent(long oldSw, short oldPort, - long newSw, short newPort, - boolean tunnelEnabled); - - /** - * Indicates if the two switch ports are connected to the same - * broadcast domain or not. - * @param s1 - * @param p1 - * @param s2 - * @param p2 - * @return - */ - public boolean isInSameBroadcastDomain(long s1, short p1, - long s2, short p2); - public boolean isInSameBroadcastDomain(long s1, short p1, - long s2, short p2, - boolean tunnelEnabled); - - /** - * Gets a list of ports on a given switch that are known to topology. - * @param sw The switch DPID in long - * @return The set of ports on this switch - */ - public Set<Short> getPortsWithLinks(long sw); - public Set<Short> getPortsWithLinks(long sw, boolean tunnelEnabled); - - /** Get broadcast ports on a target switch for a given attachmentpoint - * point port. - */ - public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort); - - public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort, - boolean tunnelEnabled); - - /** - * - */ - public boolean isIncomingBroadcastAllowed(long sw, short portId); - public boolean isIncomingBroadcastAllowed(long sw, short portId, - boolean tunnelEnabled); - - - /** Get the proper outgoing switchport for a given pair of src-dst - * switchports. - */ - public NodePortTuple getOutgoingSwitchPort(long src, short srcPort, - long dst, short dstPort); - - - public NodePortTuple getOutgoingSwitchPort(long src, short srcPort, - long dst, short dstPort, - boolean tunnelEnabled); - - - public NodePortTuple getIncomingSwitchPort(long src, short srcPort, - long dst, short dstPort); - public NodePortTuple getIncomingSwitchPort(long src, short srcPort, - long dst, short dstPort, - boolean tunnelEnabled); - - /** - * If the dst is not allowed by the higher-level topology, - * this method provides the topologically equivalent broadcast port. - * @param src - * @param dst - * @return the allowed broadcast port - */ - public NodePortTuple - getAllowedOutgoingBroadcastPort(long src, - short srcPort, - long dst, - short dstPort); - - public NodePortTuple - getAllowedOutgoingBroadcastPort(long src, - short srcPort, - long dst, - short dstPort, - boolean tunnelEnabled); - - /** - * If the src broadcast domain port is not allowed for incoming - * broadcast, this method provides the topologically equivalent - * incoming broadcast-allowed - * src port. - * @param src - * @param dst - * @return the allowed broadcast port - */ - public NodePortTuple - getAllowedIncomingBroadcastPort(long src, - short srcPort); - - public NodePortTuple - getAllowedIncomingBroadcastPort(long src, - short srcPort, - boolean tunnelEnabled); - - - /** - * Gets the set of ports that belong to a broadcast domain. - * @return The set of ports that belong to a broadcast domain. - */ - public Set<NodePortTuple> getBroadcastDomainPorts(); - public Set<NodePortTuple> getTunnelPorts(); - - - /** - * Returns a set of blocked ports. The set of blocked - * ports is the union of all the blocked ports across all - * instances. - * @return - */ - public Set<NodePortTuple> getBlockedPorts(); - - /** - * Returns the enabled, non quarantined ports of the given switch. Returns - * an empty set if switch doesn't exists, doesn't have any enabled port, or - * has only quarantined ports. Will never return null. - */ - public Set<Short> getPorts(long sw); + public void addListener(ITopologyListener listener); + + public Date getLastUpdateTime(); + + /** + * Query to determine if devices must be learned on a given switch port. + */ + public boolean isAttachmentPointPort(DatapathId switchid, OFPort port); + public boolean isAttachmentPointPort(DatapathId switchid, OFPort port, + boolean tunnelEnabled); + + public DatapathId getOpenflowDomainId(DatapathId switchId); + public DatapathId getOpenflowDomainId(DatapathId switchId, boolean tunnelEnabled); + + /** + * Returns the identifier of the L2 domain of a given switch. + * @param switchId The DPID of the switch in long form + * @return The DPID of the switch that is the key for the cluster + */ + public DatapathId getL2DomainId(DatapathId switchId); + public DatapathId getL2DomainId(DatapathId switchId, boolean tunnelEnabled); + + /** + * Queries whether two switches are in the same cluster. + * @param switch1 + * @param switch2 + * @return true if the switches are in the same cluster + */ + public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2); + public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2, + boolean tunnelEnabled); + + public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID); + public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID, + boolean tunnelEnabled); + + /** + * Queries whether two switches are in the same island. + * Currently, island and cluster are the same. In future, + * islands could be different than clusters. + * @param switch1 + * @param switch2 + * @return True of they are in the same island, false otherwise + */ + public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2); + public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2, + boolean tunnelEnabled); + + public boolean isBroadcastDomainPort(DatapathId sw, OFPort port); + public boolean isBroadcastDomainPort(DatapathId sw, OFPort port, + boolean tunnelEnabled); + + + public boolean isAllowed(DatapathId sw, OFPort portId); + public boolean isAllowed(DatapathId sw, OFPort portId, boolean tunnelEnabled); + + /** + * Indicates if an attachment point on the new switch port is consistent + * with the attachment point on the old switch port or not. + */ + public boolean isConsistent(DatapathId oldSw, OFPort oldPort, + DatapathId newSw, OFPort newPort); + public boolean isConsistent(DatapathId oldSw, OFPort oldPort, + DatapathId newSw, OFPort newPort, + boolean tunnelEnabled); + + /** + * Indicates if the two switch ports are connected to the same + * broadcast domain or not. + * @param s1 + * @param p1 + * @param s2 + * @param p2 + * @return + */ + public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1, + DatapathId s2, OFPort p2); + public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1, + DatapathId s2, OFPort p2, + boolean tunnelEnabled); + + /** + * Gets a list of ports on a given switch that are known to topology. + * @param sw The switch DPID in long + * @return The set of ports on this switch + */ + public Set<OFPort> getPortsWithLinks(DatapathId sw); + public Set<OFPort> getPortsWithLinks(DatapathId sw, boolean tunnelEnabled); + + /** Get broadcast ports on a target switch for a given attachmentpoint + * point port. + */ + public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort); + + public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort, + boolean tunnelEnabled); + + /** + * + */ + public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId); + public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId, + boolean tunnelEnabled); + + + /** Get the proper outgoing switchport for a given pair of src-dst + * switchports. + */ + public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort); + + + public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort, + boolean tunnelEnabled); + + + public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort); + public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort, + boolean tunnelEnabled); + + /** + * If the dst is not allowed by the higher-level topology, + * this method provides the topologically equivalent broadcast port. + * @param src + * @param dst + * @return the allowed broadcast port + */ + public NodePortTuple + getAllowedOutgoingBroadcastPort(DatapathId src, + OFPort srcPort, + DatapathId dst, + OFPort dstPort); + + public NodePortTuple + getAllowedOutgoingBroadcastPort(DatapathId src, + OFPort srcPort, + DatapathId dst, + OFPort dstPort, + boolean tunnelEnabled); + + /** + * If the src broadcast domain port is not allowed for incoming + * broadcast, this method provides the topologically equivalent + * incoming broadcast-allowed + * src port. + * @param src + * @param dst + * @return the allowed broadcast port + */ + public NodePortTuple + getAllowedIncomingBroadcastPort(DatapathId src, + OFPort srcPort); + + public NodePortTuple + getAllowedIncomingBroadcastPort(DatapathId src, + OFPort srcPort, + boolean tunnelEnabled); + + + /** + * Gets the set of ports that belong to a broadcast domain. + * @return The set of ports that belong to a broadcast domain. + */ + public Set<NodePortTuple> getBroadcastDomainPorts(); + public Set<NodePortTuple> getTunnelPorts(); + + + /** + * Returns a set of blocked ports. The set of blocked + * ports is the union of all the blocked ports across all + * instances. + * @return + */ + public Set<NodePortTuple> getBlockedPorts(); + + /** + * Returns the enabled, non quarantined ports of the given switch. Returns + * an empty set if switch doesn't exists, doesn't have any enabled port, or + * has only quarantined ports. Will never return null. + */ + public Set<OFPort> getPorts(DatapathId sw); } diff --git a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java index 8c5645143ac0edc54df86582d9b83273bd30ed56..f7b0a178ac397c9c2bc4bd9135c4053eb1882f96 100644 --- a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java +++ b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java @@ -21,7 +21,10 @@ import net.floodlightcontroller.core.web.serializers.UShortSerializer; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.util.HexString; /** * A NodePortTuple is similar to a SwitchPortTuple @@ -31,51 +34,46 @@ import org.openflow.util.HexString; */ public class NodePortTuple implements Comparable<NodePortTuple> { - protected long nodeId; // switch DPID - protected short portId; // switch port id + protected DatapathId nodeId; // switch DPID + protected OFPort portId; // switch port id /** * Creates a NodePortTuple * @param nodeId The DPID of the switch * @param portId The port of the switch */ - public NodePortTuple(long nodeId, short portId) { + public NodePortTuple(DatapathId nodeId, OFPort portId) { this.nodeId = nodeId; this.portId = portId; } - public NodePortTuple(long nodeId, int portId) { - this.nodeId = nodeId; - this.portId = (short) portId; - } - @JsonProperty("switch") @JsonSerialize(using=DPIDSerializer.class) - public long getNodeId() { + public DatapathId getNodeId() { return nodeId; } - public void setNodeId(long nodeId) { + public void setNodeId(DatapathId nodeId) { this.nodeId = nodeId; } @JsonProperty("port") @JsonSerialize(using=UShortSerializer.class) - public short getPortId() { + public OFPort getPortId() { return portId; } - public void setPortId(short portId) { + public void setPortId(OFPort portId) { this.portId = portId; } public String toString() { - return "[id=" + HexString.toHexString(nodeId) + ", port=" + new Short(portId) + "]"; + return "[id=" + nodeId.toString() + ", port=" + portId.toString() + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + (int) (nodeId ^ (nodeId >>> 32)); - result = prime * result + portId; + result = prime * result + (int) (nodeId.getLong() ^ (nodeId.getLong() >>> 32)); + result = prime * result + portId.getPortNumber(); return result; } @@ -102,7 +100,7 @@ public class NodePortTuple implements Comparable<NodePortTuple> { * @return */ public String toKeyString() { - return (HexString.toHexString(nodeId)+ "|" + (portId & 0xffff)); + return (nodeId.toString()+ "|" + portId.toString()); } @Override @@ -111,14 +109,14 @@ public class NodePortTuple implements Comparable<NodePortTuple> { final int EQUAL = 0; final int AFTER = 1; - if (this.getNodeId() < obj.getNodeId()) + if (this.getNodeId().getLong() < obj.getNodeId().getLong()) return BEFORE; - if (this.getNodeId() > obj.getNodeId()) + if (this.getNodeId().getLong() > obj.getNodeId().getLong()) return AFTER; - if (this.getPortId() < obj.getPortId()) + if (this.getPortId().getPortNumber() < obj.getPortId().getPortNumber()) return BEFORE; - if (this.getPortId() > obj.getPortId()) + if (this.getPortId().getPortNumber() > obj.getPortId().getPortNumber()) return AFTER; return EQUAL; diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java index a143d45e73e6bff892766999926487fb6fcb2f03..bc5d626783048f653c6c9ba63ac14f6a459709f0 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java @@ -25,7 +25,8 @@ import java.util.Map; import java.util.PriorityQueue; import java.util.Set; - +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +60,7 @@ public class TopologyInstance { protected static Logger log = LoggerFactory.getLogger(TopologyInstance.class); - protected Map<Long, Set<Short>> switchPorts; // Set of ports for each switch + protected Map<DatapathId, Set<OFPort>> switchPorts; // Set of ports for each switch /** Set of switch ports that are marked as blocked. A set of blocked * switch ports may be provided at the time of instantiation. In addition, * we may add additional ports to this set. @@ -69,17 +70,17 @@ public class TopologyInstance { /** Set of links that are blocked. */ protected Set<Link> blockedLinks; - protected Set<Long> switches; + protected Set<DatapathId> switches; protected Set<NodePortTuple> broadcastDomainPorts; protected Set<NodePortTuple> tunnelPorts; protected Set<Cluster> clusters; // set of openflow domains - protected Map<Long, Cluster> switchClusterMap; // switch to OF domain map + protected Map<DatapathId, Cluster> switchClusterMap; // switch to OF domain map // States for routing - protected Map<Long, BroadcastTree> destinationRootedTrees; - protected Map<Long, Set<NodePortTuple>> clusterBroadcastNodePorts; - protected Map<Long, BroadcastTree> clusterBroadcastTrees; + protected Map<DatapathId, BroadcastTree> destinationRootedTrees; + protected Map<DatapathId, Set<NodePortTuple>> clusterBroadcastNodePorts; + protected Map<DatapathId, BroadcastTree> clusterBroadcastTrees; protected class PathCacheLoader extends CacheLoader<RouteId, Route> { TopologyInstance ti; @@ -99,8 +100,8 @@ public class TopologyInstance { protected LoadingCache<RouteId, Route> pathcache; public TopologyInstance() { - this.switches = new HashSet<Long>(); - this.switchPorts = new HashMap<Long, Set<Short>>(); + this.switches = new HashSet<DatapathId>(); + this.switchPorts = new HashMap<DatapathId, Set<OFPort>>(); this.switchPortLinks = new HashMap<NodePortTuple, Set<Link>>(); this.broadcastDomainPorts = new HashSet<NodePortTuple>(); this.tunnelPorts = new HashSet<NodePortTuple>(); @@ -108,12 +109,12 @@ public class TopologyInstance { this.blockedLinks = new HashSet<Link>(); } - public TopologyInstance(Map<Long, Set<Short>> switchPorts, + public TopologyInstance(Map<DatapathId, Set<OFPort>> switchPorts, Map<NodePortTuple, Set<Link>> switchPortLinks, Set<NodePortTuple> broadcastDomainPorts) { - this.switches = new HashSet<Long>(switchPorts.keySet()); - this.switchPorts = new HashMap<Long, Set<Short>>(switchPorts); + this.switches = new HashSet<DatapathId>(switchPorts.keySet()); + this.switchPorts = new HashMap<DatapathId, Set<OFPort>>(switchPorts); this.switchPortLinks = new HashMap<NodePortTuple, Set<Link>>(switchPortLinks); this.broadcastDomainPorts = new HashSet<NodePortTuple>(broadcastDomainPorts); @@ -122,19 +123,19 @@ public class TopologyInstance { this.blockedLinks = new HashSet<Link>(); clusters = new HashSet<Cluster>(); - switchClusterMap = new HashMap<Long, Cluster>(); + switchClusterMap = new HashMap<DatapathId, Cluster>(); } - public TopologyInstance(Map<Long, Set<Short>> switchPorts, + public TopologyInstance(Map<DatapathId, Set<OFPort>> switchPorts, Set<NodePortTuple> blockedPorts, Map<NodePortTuple, Set<Link>> switchPortLinks, Set<NodePortTuple> broadcastDomainPorts, Set<NodePortTuple> tunnelPorts){ // copy these structures - this.switches = new HashSet<Long>(switchPorts.keySet()); - this.switchPorts = new HashMap<Long, Set<Short>>(); - for(long sw: switchPorts.keySet()) { - this.switchPorts.put(sw, new HashSet<Short>(switchPorts.get(sw))); + this.switches = new HashSet<DatapathId>(switchPorts.keySet()); + this.switchPorts = new HashMap<DatapathId, Set<OFPort>>(); + for(DatapathId sw: switchPorts.keySet()) { + this.switchPorts.put(sw, new HashSet<OFPort>(switchPorts.get(sw))); } this.blockedPorts = new HashSet<NodePortTuple>(blockedPorts); @@ -148,10 +149,10 @@ public class TopologyInstance { blockedLinks = new HashSet<Link>(); clusters = new HashSet<Cluster>(); - switchClusterMap = new HashMap<Long, Cluster>(); - destinationRootedTrees = new HashMap<Long, BroadcastTree>(); - clusterBroadcastTrees = new HashMap<Long, BroadcastTree>(); - clusterBroadcastNodePorts = new HashMap<Long, Set<NodePortTuple>>(); + switchClusterMap = new HashMap<DatapathId, Cluster>(); + destinationRootedTrees = new HashMap<DatapathId, BroadcastTree>(); + clusterBroadcastTrees = new HashMap<DatapathId, BroadcastTree>(); + clusterBroadcastNodePorts = new HashMap<DatapathId, Set<NodePortTuple>>(); pathcache = CacheBuilder.newBuilder().concurrencyLevel(4) .maximumSize(1000L) @@ -204,9 +205,9 @@ public class TopologyInstance { } protected void addLinksToOpenflowDomains() { - for(long s: switches) { + for(DatapathId s: switches) { if (switchPorts.get(s) == null) continue; - for (short p: switchPorts.get(s)) { + for (OFPort p: switchPorts.get(s)) { NodePortTuple np = new NodePortTuple(s, p); if (switchPortLinks.get(np) == null) continue; if (isBroadcastDomainPort(np)) continue; @@ -242,17 +243,17 @@ public class TopologyInstance { explanation="The internal state of the topology module is corrupt", recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) public void identifyOpenflowDomains() { - Map<Long, ClusterDFS> dfsList = new HashMap<Long, ClusterDFS>(); + Map<DatapathId, ClusterDFS> dfsList = new HashMap<DatapathId, ClusterDFS>(); if (switches == null) return; - for (Long key: switches) { + for (DatapathId key: switches) { ClusterDFS cdfs = new ClusterDFS(); dfsList.put(key, cdfs); } - Set<Long> currSet = new HashSet<Long>(); + Set<DatapathId> currSet = new HashSet<DatapathId>(); - for (Long sw: switches) { + for (DatapathId sw: switches) { ClusterDFS cdfs = dfsList.get(sw); if (cdfs == null) { log.error("No DFS object for switch {} found.", sw); @@ -291,15 +292,15 @@ public class TopologyInstance { * @param currSet: Set of nodes in the current cluster in formation * @return long: DSF index to be used when a new node is visited */ - private long dfsTraverse (long parentIndex, long currIndex, long currSw, - Map<Long, ClusterDFS> dfsList, Set <Long> currSet) { + private long dfsTraverse (long parentIndex, long currIndex, DatapathId currSw, + Map<DatapathId, ClusterDFS> dfsList, Set <DatapathId> currSet) { //Get the DFS object corresponding to the current switch ClusterDFS currDFS = dfsList.get(currSw); // Get all the links corresponding to this switch - Set<Long> nodesInMyCluster = new HashSet<Long>(); - Set<Long> myCurrSet = new HashSet<Long>(); + Set<DatapathId> nodesInMyCluster = new HashSet<DatapathId>(); + Set<DatapathId> myCurrSet = new HashSet<DatapathId>(); //Assign the DFS object with right values. currDFS.setVisited(true); @@ -309,14 +310,14 @@ public class TopologyInstance { // Traverse the graph through every outgoing link. if (switchPorts.get(currSw) != null){ - for(Short p: switchPorts.get(currSw)) { + for(OFPort p: switchPorts.get(currSw)) { Set<Link> lset = switchPortLinks.get(new NodePortTuple(currSw, p)); if (lset == null) continue; for(Link l:lset) { - long dstSw = l.getDst(); + DatapathId dstSw = l.getDst(); // ignore incoming links. - if (dstSw == currSw) continue; + if (dstSw.equals(currSw)) continue; // ignore if the destination is already added to // another cluster @@ -368,7 +369,7 @@ public class TopologyInstance { // create a new switch cluster and the switches in the current // set to the switch cluster. Cluster sc = new Cluster(); - for(long sw: currSet){ + for(DatapathId sw: currSet){ sc.add(sw); switchClusterMap.put(sw, sc); } @@ -425,8 +426,8 @@ public class TopologyInstance { } protected class NodeDist implements Comparable<NodeDist> { - private final Long node; - public Long getNode() { + private final DatapathId node; + public DatapathId getNode() { return node; } @@ -435,7 +436,7 @@ public class TopologyInstance { return dist; } - public NodeDist(Long node, int dist) { + public NodeDist(DatapathId node, int dist) { this.node = node; this.dist = dist; } @@ -443,7 +444,7 @@ public class TopologyInstance { @Override public int compareTo(NodeDist o) { if (o.dist == this.dist) { - return (int)(this.node - o.node); + return (int)(this.node.getLong() - o.node.getLong()); } return this.dist - o.dist; } @@ -478,34 +479,34 @@ public class TopologyInstance { } } - protected BroadcastTree dijkstra(Cluster c, Long root, + protected BroadcastTree dijkstra(Cluster c, DatapathId root, Map<Link, Integer> linkCost, boolean isDstRooted) { - HashMap<Long, Link> nexthoplinks = new HashMap<Long, Link>(); + HashMap<DatapathId, Link> nexthoplinks = new HashMap<DatapathId, Link>(); //HashMap<Long, Long> nexthopnodes = new HashMap<Long, Long>(); - HashMap<Long, Integer> cost = new HashMap<Long, Integer>(); + HashMap<DatapathId, Integer> cost = new HashMap<DatapathId, Integer>(); int w; - for (Long node: c.links.keySet()) { + for (DatapathId node: c.links.keySet()) { nexthoplinks.put(node, null); //nexthopnodes.put(node, null); cost.put(node, MAX_PATH_WEIGHT); } - HashMap<Long, Boolean> seen = new HashMap<Long, Boolean>(); + HashMap<DatapathId, Boolean> seen = new HashMap<DatapathId, Boolean>(); PriorityQueue<NodeDist> nodeq = new PriorityQueue<NodeDist>(); nodeq.add(new NodeDist(root, 0)); cost.put(root, 0); while (nodeq.peek() != null) { NodeDist n = nodeq.poll(); - Long cnode = n.getNode(); + DatapathId cnode = n.getNode(); int cdist = n.getDist(); if (cdist >= MAX_PATH_WEIGHT) break; if (seen.containsKey(cnode)) continue; seen.put(cnode, true); for (Link link: c.links.get(cnode)) { - Long neighbor; + DatapathId neighbor; if (isDstRooted == true) neighbor = link.getSrc(); else neighbor = link.getDst(); @@ -554,7 +555,7 @@ public class TopologyInstance { } for(Cluster c: clusters) { - for (Long node : c.links.keySet()) { + for (DatapathId node : c.links.keySet()) { BroadcastTree tree = dijkstra(c, node, linkCost, true); destinationRootedTrees.put(node, tree); } @@ -581,9 +582,9 @@ public class TopologyInstance { //log.info("Broadcast Tree {}", tree); Set<NodePortTuple> nptSet = new HashSet<NodePortTuple>(); - Map<Long, Link> links = tree.getLinks(); + Map<DatapathId, Link> links = tree.getLinks(); if (links == null) continue; - for(long nodeId: links.keySet()) { + for(DatapathId nodeId: links.keySet()) { Link l = links.get(nodeId); if (l == null) continue; NodePortTuple npt1 = new NodePortTuple(l.getSrc(), l.getSrcPort()); @@ -597,8 +598,8 @@ public class TopologyInstance { protected Route buildroute(RouteId id) { NodePortTuple npt; - long srcId = id.getSrc(); - long dstId = id.getDst(); + DatapathId srcId = id.getSrc(); + DatapathId dstId = id.getDst(); LinkedList<NodePortTuple> switchPorts = new LinkedList<NodePortTuple>(); @@ -606,7 +607,7 @@ public class TopologyInstance { if (destinationRootedTrees == null) return null; if (destinationRootedTrees.get(dstId) == null) return null; - Map<Long, Link> nexthoplinks = + Map<DatapathId, Link> nexthoplinks = destinationRootedTrees.get(dstId).getLinks(); if (!switches.contains(srcId) || !switches.contains(dstId)) { @@ -640,7 +641,7 @@ public class TopologyInstance { return result; } - protected int getCost(long srcId, long dstId) { + protected int getCost(DatapathId srcId, DatapathId dstId) { BroadcastTree bt = destinationRootedTrees.get(dstId); if (bt == null) return -1; return (bt.getCost(srcId)); @@ -655,7 +656,7 @@ public class TopologyInstance { } // IRoutingEngineService interfaces - protected boolean routeExists(long srcId, long dstId) { + protected boolean routeExists(DatapathId srcId, DatapathId dstId) { BroadcastTree bt = destinationRootedTrees.get(dstId); if (bt == null) return false; Link link = bt.getLinks().get(srcId); @@ -663,19 +664,19 @@ public class TopologyInstance { return true; } - protected Route getRoute(ServiceChain sc, long srcId, short srcPort, - long dstId, short dstPort, long cookie) { + protected Route getRoute(ServiceChain sc, DatapathId srcId, OFPort srcPort, + DatapathId dstId, OFPort dstPort, long cookie) { // Return null the route source and desitnation are the // same switchports. - if (srcId == dstId && srcPort == dstPort) + if (srcId.equals(dstId) && srcPort.equals(dstPort)) return null; List<NodePortTuple> nptList; NodePortTuple npt; Route r = getRoute(srcId, dstId, 0); - if (r == null && srcId != dstId) return null; + if (r == null && !srcId.equals(dstId)) return null; if (r != null) { nptList= new ArrayList<NodePortTuple>(r.getPath()); @@ -695,9 +696,9 @@ public class TopologyInstance { // NOTE: Return a null route if srcId equals dstId. The null route // need not be stored in the cache. Moreover, the LoadingCache will // throw an exception if null route is returned. - protected Route getRoute(long srcId, long dstId, long cookie) { + protected Route getRoute(DatapathId srcId, DatapathId dstId, long cookie) { // Return null route if srcId equals dstId - if (srcId == dstId) return null; + if (srcId.equals(dstId)) return null; RouteId id = new RouteId(srcId, dstId); @@ -725,54 +726,54 @@ public class TopologyInstance { // ITopologyService interface method helpers. // - protected boolean isInternalToOpenflowDomain(long switchid, short port) { + protected boolean isInternalToOpenflowDomain(DatapathId switchid, OFPort port) { return !isAttachmentPointPort(switchid, port); } - public boolean isAttachmentPointPort(long switchid, short port) { + public boolean isAttachmentPointPort(DatapathId switchid, OFPort port) { NodePortTuple npt = new NodePortTuple(switchid, port); if (switchPortLinks.containsKey(npt)) return false; return true; } - protected long getOpenflowDomainId(long switchId) { + protected DatapathId getOpenflowDomainId(DatapathId switchId) { Cluster c = switchClusterMap.get(switchId); if (c == null) return switchId; return c.getId(); } - protected long getL2DomainId(long switchId) { + protected DatapathId getL2DomainId(DatapathId switchId) { return getOpenflowDomainId(switchId); } - protected Set<Long> getSwitchesInOpenflowDomain(long switchId) { + protected Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchId) { Cluster c = switchClusterMap.get(switchId); if (c == null) { // The switch is not known to topology as there // are no links connected to it. - Set<Long> nodes = new HashSet<Long>(); + Set<DatapathId> nodes = new HashSet<DatapathId>(); nodes.add(switchId); return nodes; } return (c.getNodes()); } - protected boolean inSameOpenflowDomain(long switch1, long switch2) { + protected boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2) { Cluster c1 = switchClusterMap.get(switch1); Cluster c2 = switchClusterMap.get(switch2); if (c1 != null && c2 != null) - return (c1.getId() == c2.getId()); - return (switch1 == switch2); + return (c1.getId().equals(c2.getId())); + return (switch1.equals(switch2)); } - public boolean isAllowed(long sw, short portId) { + public boolean isAllowed(DatapathId sw, OFPort portId) { return true; } protected boolean - isIncomingBroadcastAllowedOnSwitchPort(long sw, short portId) { + isIncomingBroadcastAllowedOnSwitchPort(DatapathId sw, OFPort portId) { if (isInternalToOpenflowDomain(sw, portId)) { - long clusterId = getOpenflowDomainId(sw); + DatapathId clusterId = getOpenflowDomainId(sw); NodePortTuple npt = new NodePortTuple(sw, portId); if (clusterBroadcastNodePorts.get(clusterId).contains(npt)) return true; @@ -781,52 +782,52 @@ public class TopologyInstance { return true; } - public boolean isConsistent(long oldSw, short oldPort, long newSw, - short newPort) { + public boolean isConsistent(DatapathId oldSw, OFPort oldPort, DatapathId newSw, + OFPort newPort) { if (isInternalToOpenflowDomain(newSw, newPort)) return true; - return (oldSw == newSw && oldPort == newPort); + return (oldSw.equals(newSw) && oldPort.equals(newPort)); } protected Set<NodePortTuple> - getBroadcastNodePortsInCluster(long sw) { - long clusterId = getOpenflowDomainId(sw); + getBroadcastNodePortsInCluster(DatapathId sw) { + DatapathId clusterId = getOpenflowDomainId(sw); return clusterBroadcastNodePorts.get(clusterId); } - public boolean inSameBroadcastDomain(long s1, short p1, long s2, short p2) { + public boolean inSameBroadcastDomain(DatapathId s1, OFPort p1, DatapathId s2, OFPort p2) { return false; } - public boolean inSameL2Domain(long switch1, long switch2) { + public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2) { return inSameOpenflowDomain(switch1, switch2); } - public NodePortTuple getOutgoingSwitchPort(long src, short srcPort, - long dst, short dstPort) { + public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort) { // Use this function to redirect traffic if needed. return new NodePortTuple(dst, dstPort); } - public NodePortTuple getIncomingSwitchPort(long src, short srcPort, - long dst, short dstPort) { + public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort) { // Use this function to reinject traffic from a // different port if needed. return new NodePortTuple(src, srcPort); } - public Set<Long> getSwitches() { + public Set<DatapathId> getSwitches() { return switches; } - public Set<Short> getPortsWithLinks(long sw) { + public Set<OFPort> getPortsWithLinks(DatapathId sw) { return switchPorts.get(sw); } - public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort) { - Set<Short> result = new HashSet<Short>(); - long clusterId = getOpenflowDomainId(targetSw); + public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort) { + Set<OFPort> result = new HashSet<OFPort>(); + DatapathId clusterId = getOpenflowDomainId(targetSw); for(NodePortTuple npt: clusterBroadcastNodePorts.get(clusterId)) { - if (npt.getNodeId() == targetSw) { + if (npt.getNodeId().equals(targetSw)) { result.add(npt.getPortId()); } } @@ -834,15 +835,13 @@ public class TopologyInstance { } public NodePortTuple - getAllowedOutgoingBroadcastPort(long src, short srcPort, long dst, - short dstPort) { - // TODO Auto-generated method stub + getAllowedOutgoingBroadcastPort(DatapathId src, OFPort srcPort, DatapathId dst, + OFPort dstPort) { return null; } public NodePortTuple - getAllowedIncomingBroadcastPort(long src, short srcPort) { - // TODO Auto-generated method stub + getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort) { return null; } } diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java index 25b91464a1dd7aa8213e4987a0d0bf77abc6d39a..dce7d28b92a0928d211a245ad49f678a1af87685 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java @@ -33,13 +33,15 @@ import java.util.concurrent.TimeUnit; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.HAListenerTypeMarker; +import net.floodlightcontroller.core.HARole; import net.floodlightcontroller.core.IFloodlightProviderService; -import net.floodlightcontroller.core.IFloodlightProviderService.Role; import net.floodlightcontroller.core.IHAListener; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.LogicalOFMessageCategory; import net.floodlightcontroller.core.annotations.LogMessageCategory; import net.floodlightcontroller.core.annotations.LogMessageDoc; +import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; @@ -50,7 +52,7 @@ import net.floodlightcontroller.debugcounter.IDebugCounter; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException; import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType; -import net.floodlightcontroller.debugcounter.NullDebugCounter; +import net.floodlightcontroller.debugcounter.MockDebugCounterService; import net.floodlightcontroller.debugevent.IDebugEventService; import net.floodlightcontroller.debugevent.IEventUpdater; import net.floodlightcontroller.debugevent.NullDebugEvent; @@ -70,13 +72,16 @@ import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.topology.web.TopologyWebRoutable; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -101,12 +106,12 @@ public class TopologyManager implements /** * Role of the controller. */ - private Role role; + private HARole role; /** * Set of ports for each switch */ - protected Map<Long, Set<Short>> switchPorts; + protected Map<DatapathId, Set<OFPort>> switchPorts; /** * Set of links organized by node port tuple @@ -131,6 +136,7 @@ public class TopologyManager implements protected ILinkDiscoveryService linkDiscovery; protected IThreadPoolService threadPool; protected IFloodlightProviderService floodlightProvider; + protected IOFSwitchService switchService; protected IRestApiService restApi; protected IDebugCounterService debugCounters; @@ -188,11 +194,11 @@ public class TopologyManager implements protected class TopologyEventInfo { private final int numOpenflowClustersWithTunnels; private final int numOpenflowClustersWithoutTunnels; - private final Map<Long, List<NodePortTuple>> externalPortsMap; + private final Map<DatapathId, List<NodePortTuple>> externalPortsMap; private final int numTunnelPorts; public TopologyEventInfo(int numOpenflowClustersWithTunnels, int numOpenflowClustersWithoutTunnels, - Map<Long, List<NodePortTuple>> externalPortsMap, + Map<DatapathId, List<NodePortTuple>> externalPortsMap, int numTunnelPorts) { super(); this.numOpenflowClustersWithTunnels = numOpenflowClustersWithTunnels; @@ -215,7 +221,7 @@ public class TopologyManager implements if (numExternalClusters > 0) { builder.append(" { "); int count = 0; - for (Long extCluster : externalPortsMap.keySet()) { + for (DatapathId extCluster : externalPortsMap.keySet()) { builder.append("#" + extCluster + ":Ext Ports: "); builder.append(externalPortsMap.get(extCluster).size()); if (++count < numExternalClusters) { @@ -287,7 +293,7 @@ public class TopologyManager implements catch (Exception e) { log.error("Error in topology instance task thread", e); } finally { - if (floodlightProvider.getRole() != Role.SLAVE) + if (floodlightProvider.getRole() != HARole.STANDBY) newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS); } @@ -348,12 +354,12 @@ public class TopologyManager implements } @Override - public boolean isAttachmentPointPort(long switchid, short port) { + public boolean isAttachmentPointPort(DatapathId switchid, OFPort port) { return isAttachmentPointPort(switchid, port, true); } @Override - public boolean isAttachmentPointPort(long switchid, short port, + public boolean isAttachmentPointPort(DatapathId switchid, OFPort port, boolean tunnelEnabled) { // If the switch port is 'tun-bsn' port, it is not @@ -371,55 +377,56 @@ public class TopologyManager implements // Check whether the port is a physical port. We should not learn // attachment points on "special" ports. - if ((port & 0xff00) == 0xff00 && port != (short)0xfffe) return false; + //TODO @Ryan port numbers should be handled as ints now, not shorts. I suppose anything above 65280 up to 65533 is a "special" non-physical port. + if ((port.getShortPortNumber() & 0xff00) == 0xff00 && port.getShortPortNumber() != (short)0xfffe) return false; // Make sure that the port is enabled. - IOFSwitch sw = floodlightProvider.getSwitch(switchid); + IOFSwitch sw = switchService.getActiveSwitch(switchid); if (sw == null) return false; return (sw.portEnabled(port)); } @Override - public long getOpenflowDomainId(long switchId) { + public DatapathId getOpenflowDomainId(DatapathId switchId) { return getOpenflowDomainId(switchId, true); } @Override - public long getOpenflowDomainId(long switchId, boolean tunnelEnabled) { + public DatapathId getOpenflowDomainId(DatapathId switchId, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getOpenflowDomainId(switchId); } @Override - public long getL2DomainId(long switchId) { + public DatapathId getL2DomainId(DatapathId switchId) { return getL2DomainId(switchId, true); } @Override - public long getL2DomainId(long switchId, boolean tunnelEnabled) { + public DatapathId getL2DomainId(DatapathId switchId, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getL2DomainId(switchId); } @Override - public boolean inSameOpenflowDomain(long switch1, long switch2) { + public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2) { return inSameOpenflowDomain(switch1, switch2, true); } @Override - public boolean inSameOpenflowDomain(long switch1, long switch2, + public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.inSameOpenflowDomain(switch1, switch2); } @Override - public boolean isAllowed(long sw, short portId) { + public boolean isAllowed(DatapathId sw, OFPort portId) { return isAllowed(sw, portId, true); } @Override - public boolean isAllowed(long sw, short portId, boolean tunnelEnabled) { + public boolean isAllowed(DatapathId sw, OFPort portId, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.isAllowed(sw, portId); } @@ -427,12 +434,12 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @Override - public boolean isIncomingBroadcastAllowed(long sw, short portId) { + public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId) { return isIncomingBroadcastAllowed(sw, portId, true); } @Override - public boolean isIncomingBroadcastAllowed(long sw, short portId, + public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.isIncomingBroadcastAllowedOnSwitchPort(sw, portId); @@ -442,13 +449,13 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// /** Get all the ports connected to the switch */ @Override - public Set<Short> getPortsWithLinks(long sw) { + public Set<OFPort> getPortsWithLinks(DatapathId sw) { return getPortsWithLinks(sw, true); } /** Get all the ports connected to the switch */ @Override - public Set<Short> getPortsWithLinks(long sw, boolean tunnelEnabled) { + public Set<OFPort> getPortsWithLinks(DatapathId sw, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getPortsWithLinks(sw); } @@ -460,8 +467,8 @@ public class TopologyManager implements * is on switch port (src, srcPort). */ @Override - public Set<Short> getBroadcastPorts(long targetSw, - long src, short srcPort) { + public Set<OFPort> getBroadcastPorts(DatapathId targetSw, + DatapathId src, OFPort srcPort) { return getBroadcastPorts(targetSw, src, srcPort, true); } @@ -470,8 +477,8 @@ public class TopologyManager implements * is on switch port (src, srcPort). */ @Override - public Set<Short> getBroadcastPorts(long targetSw, - long src, short srcPort, + public Set<OFPort> getBroadcastPorts(DatapathId targetSw, + DatapathId src, OFPort srcPort, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getBroadcastPorts(targetSw, src, srcPort); @@ -480,15 +487,15 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @Override - public NodePortTuple getOutgoingSwitchPort(long src, short srcPort, - long dst, short dstPort) { + public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort) { // Use this function to redirect traffic if needed. return getOutgoingSwitchPort(src, srcPort, dst, dstPort, true); } @Override - public NodePortTuple getOutgoingSwitchPort(long src, short srcPort, - long dst, short dstPort, + public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort, boolean tunnelEnabled) { // Use this function to redirect traffic if needed. TopologyInstance ti = getCurrentInstance(tunnelEnabled); @@ -499,14 +506,14 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @Override - public NodePortTuple getIncomingSwitchPort(long src, short srcPort, - long dst, short dstPort) { + public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort) { return getIncomingSwitchPort(src, srcPort, dst, dstPort, true); } @Override - public NodePortTuple getIncomingSwitchPort(long src, short srcPort, - long dst, short dstPort, + public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort, + DatapathId dst, OFPort dstPort, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getIncomingSwitchPort(src, srcPort, @@ -519,15 +526,15 @@ public class TopologyManager implements * Checks if the two switchports belong to the same broadcast domain. */ @Override - public boolean isInSameBroadcastDomain(long s1, short p1, long s2, - short p2) { + public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1, DatapathId s2, + OFPort p2) { return isInSameBroadcastDomain(s1, p1, s2, p2, true); } @Override - public boolean isInSameBroadcastDomain(long s1, short p1, - long s2, short p2, + public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1, + DatapathId s2, OFPort p2, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.inSameBroadcastDomain(s1, p1, s2, p2); @@ -540,12 +547,12 @@ public class TopologyManager implements * Checks if the switchport is a broadcast domain port or not. */ @Override - public boolean isBroadcastDomainPort(long sw, short port) { + public boolean isBroadcastDomainPort(DatapathId sw, OFPort port) { return isBroadcastDomainPort(sw, port, true); } @Override - public boolean isBroadcastDomainPort(long sw, short port, + public boolean isBroadcastDomainPort(DatapathId sw, OFPort port, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.isBroadcastDomainPort(new NodePortTuple(sw, port)); @@ -558,15 +565,15 @@ public class TopologyManager implements * old attachment point port. */ @Override - public boolean isConsistent(long oldSw, short oldPort, - long newSw, short newPort) { + public boolean isConsistent(DatapathId oldSw, OFPort oldPort, + DatapathId newSw, OFPort newPort) { return isConsistent(oldSw, oldPort, newSw, newPort, true); } @Override - public boolean isConsistent(long oldSw, short oldPort, - long newSw, short newPort, + public boolean isConsistent(DatapathId oldSw, OFPort oldPort, + DatapathId newSw, OFPort newPort, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.isConsistent(oldSw, oldPort, newSw, newPort); @@ -578,12 +585,12 @@ public class TopologyManager implements * Checks if the two switches are in the same Layer 2 domain. */ @Override - public boolean inSameL2Domain(long switch1, long switch2) { + public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2) { return inSameL2Domain(switch1, switch2, true); } @Override - public boolean inSameL2Domain(long switch1, long switch2, + public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.inSameL2Domain(switch1, switch2); @@ -592,19 +599,19 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @Override - public NodePortTuple getAllowedOutgoingBroadcastPort(long src, - short srcPort, - long dst, - short dstPort) { + public NodePortTuple getAllowedOutgoingBroadcastPort(DatapathId src, + OFPort srcPort, + DatapathId dst, + OFPort dstPort) { return getAllowedOutgoingBroadcastPort(src, srcPort, dst, dstPort, true); } @Override - public NodePortTuple getAllowedOutgoingBroadcastPort(long src, - short srcPort, - long dst, - short dstPort, + public NodePortTuple getAllowedOutgoingBroadcastPort(DatapathId src, + OFPort srcPort, + DatapathId dst, + OFPort dstPort, boolean tunnelEnabled){ TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getAllowedOutgoingBroadcastPort(src, srcPort, @@ -614,13 +621,13 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// @Override public NodePortTuple - getAllowedIncomingBroadcastPort(long src, short srcPort) { + getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort) { return getAllowedIncomingBroadcastPort(src,srcPort, true); } @Override public NodePortTuple - getAllowedIncomingBroadcastPort(long src, short srcPort, + getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getAllowedIncomingBroadcastPort(src,srcPort); @@ -629,12 +636,12 @@ public class TopologyManager implements //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @Override - public Set<Long> getSwitchesInOpenflowDomain(long switchDPID) { + public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID) { return getSwitchesInOpenflowDomain(switchDPID, true); } @Override - public Set<Long> getSwitchesInOpenflowDomain(long switchDPID, + public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getSwitchesInOpenflowDomain(switchDPID); @@ -678,41 +685,41 @@ public class TopologyManager implements // *************** @Override - public Route getRoute(long src, long dst, long cookie) { + public Route getRoute(DatapathId src, DatapathId dst, long cookie) { return getRoute(src, dst, cookie, true); } @Override - public Route getRoute(long src, long dst, long cookie, boolean tunnelEnabled) { + public Route getRoute(DatapathId src, DatapathId dst, long cookie, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getRoute(src, dst, cookie); } @Override - public Route getRoute(long src, short srcPort, long dst, short dstPort, long cookie) { + public Route getRoute(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort, long cookie) { return getRoute(src, srcPort, dst, dstPort, cookie, true); } @Override - public Route getRoute(long src, short srcPort, long dst, short dstPort, long cookie, + public Route getRoute(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort, long cookie, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.getRoute(null, src, srcPort, dst, dstPort, cookie); } @Override - public boolean routeExists(long src, long dst) { + public boolean routeExists(DatapathId src, DatapathId dst) { return routeExists(src, dst, true); } @Override - public boolean routeExists(long src, long dst, boolean tunnelEnabled) { + public boolean routeExists(DatapathId src, DatapathId dst, boolean tunnelEnabled) { TopologyInstance ti = getCurrentInstance(tunnelEnabled); return ti.routeExists(src, dst); } @Override - public ArrayList<Route> getRoutes(long srcDpid, long dstDpid, + public ArrayList<Route> getRoutes(DatapathId srcDpid, DatapathId dstDpid, boolean tunnelEnabled) { // Floodlight supports single path routing now @@ -746,7 +753,7 @@ public class TopologyManager implements FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: - ctrIncoming.updateCounterNoFlush(); + ctrIncoming.increment(); return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx); default: @@ -762,10 +769,10 @@ public class TopologyManager implements private class HAListenerDelegate implements IHAListener { @Override - public void transitionToMaster() { - role = Role.MASTER; + public void transitionToActive() { + role = HARole.ACTIVE; log.debug("Re-computing topology due " + - "to HA change from SLAVE->MASTER"); + "to HA change from STANDBY->ACTIVE"); newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS); } @@ -796,6 +803,12 @@ public class TopologyManager implements // TODO Auto-generated method stub return false; } + + @Override + public void transitionToStandby() { + // TODO Auto-generated method stub + + } } // ***************** @@ -832,6 +845,7 @@ public class TopologyManager implements l.add(ILinkDiscoveryService.class); l.add(IThreadPoolService.class); l.add(IFloodlightProviderService.class); + l.add(IOFSwitchService.class); l.add(ICounterStoreService.class); l.add(IRestApiService.class); return l; @@ -844,11 +858,12 @@ public class TopologyManager implements threadPool = context.getServiceImpl(IThreadPoolService.class); floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); + switchService = context.getServiceImpl(IOFSwitchService.class); restApi = context.getServiceImpl(IRestApiService.class); debugCounters = context.getServiceImpl(IDebugCounterService.class); debugEvents = context.getServiceImpl(IDebugEventService.class); - switchPorts = new HashMap<Long,Set<Short>>(); + switchPorts = new HashMap<DatapathId, Set<OFPort>>(); switchPortLinks = new HashMap<NodePortTuple, Set<Link>>(); directLinks = new HashMap<NodePortTuple, Set<Link>>(); portBroadcastDomainLinks = new HashMap<NodePortTuple, Set<Link>>(); @@ -884,7 +899,7 @@ public class TopologyManager implements ScheduledExecutorService ses = threadPool.getScheduledExecutor(); newInstanceTask = new SingletonTask(ses, new UpdateTopologyWorker()); - if (role != Role.SLAVE) + if (role != HARole.STANDBY) newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS); @@ -924,17 +939,17 @@ public class TopologyManager implements * @param cntx * @return */ - protected Command dropFilter(long sw, OFPacketIn pi, + protected Command dropFilter(DatapathId sw, OFPacketIn pi, FloodlightContext cntx) { Command result = Command.CONTINUE; - short port = pi.getInPort(); + OFPort port = pi.getInPort(); // If the input port is not allowed for data traffic, drop everything. // BDDP packets will not reach this stage. if (isAllowed(sw, port) == false) { if (log.isTraceEnabled()) { log.trace("Ignoring packet because of topology " + - "restriction on switch={}, port={}", sw, port); + "restriction on switch={}, port={}", sw.getLong(), port.getPortNumber()); result = Command.STOP; } } @@ -955,49 +970,45 @@ public class TopologyManager implements "topology discovery packet", recommendation=LogMessageDoc.CHECK_SWITCH) public void doMultiActionPacketOut(byte[] packetData, IOFSwitch sw, - Set<Short> ports, + Set<OFPort> ports, FloodlightContext cntx) { if (ports == null) return; if (packetData == null || packetData.length <= 0) return; - OFPacketOut po = - (OFPacketOut) floodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_OUT); - + //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT); + OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut(); List<OFAction> actions = new ArrayList<OFAction>(); - for(short p: ports) { - actions.add(new OFActionOutput(p, (short) 0)); + for(OFPort p: ports) { + //actions.add(new OFActionOutput(p, (short) 0)); + actions.add(sw.getOFFactory().actions().output(p, 0)); } // set actions - po.setActions(actions); + pob.setActions(actions); // set action length - po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * - ports.size())); + //po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * ports.size())); // set buffer-id to BUFFER_ID_NONE - po.setBufferId(OFPacketOut.BUFFER_ID_NONE); + pob.setBufferId(OFBufferId.NO_BUFFER); // set in-port to OFPP_NONE - po.setInPort(OFPort.OFPP_NONE.getValue()); + pob.setInPort(OFPort.ZERO); // set packet data - po.setPacketData(packetData); + pob.setData(packetData); // compute and set packet length. - short poLength = (short)(OFPacketOut.MINIMUM_LENGTH + - po.getActionsLength() + - packetData.length); + //short poLength = (short)(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length); - po.setLength(poLength); + //po.setLength(poLength); try { //counterStore.updatePktOutFMCounterStore(sw, po); if (log.isTraceEnabled()) { log.trace("write broadcast packet on switch-id={} " + "interaces={} packet-data={} packet-out={}", - new Object[] {sw.getId(), ports, packetData, po}); + new Object[] {sw.getId(), ports, packetData, pob.build()}); } - sw.write(po, cntx); + sw.write(pob.build(), LogicalOFMessageCategory.MAIN); } catch (IOException e) { log.error("Failure writing packet out", e); @@ -1012,11 +1023,11 @@ public class TopologyManager implements * @param sid * @return */ - protected Set<Short> getPortsToEliminateForBDDP(long sid) { + protected Set<OFPort> getPortsToEliminateForBDDP(DatapathId sid) { Set<NodePortTuple> suppressedNptList = linkDiscovery.getSuppressLLDPsInfo(); if (suppressedNptList == null) return null; - Set<Short> resultPorts = new HashSet<Short>(); + Set<OFPort> resultPorts = new HashSet<OFPort>(); for(NodePortTuple npt: suppressedNptList) { if (npt.getNodeId() == sid) { resultPorts.add(npt.getPortId()); @@ -1035,36 +1046,36 @@ public class TopologyManager implements * @param pi * @param cntx */ - protected void doFloodBDDP(long pinSwitch, OFPacketIn pi, + protected void doFloodBDDP(DatapathId pinSwitch, OFPacketIn pi, FloodlightContext cntx) { TopologyInstance ti = getCurrentInstance(false); - Set<Long> switches = ti.getSwitchesInOpenflowDomain(pinSwitch); + Set<DatapathId> switches = ti.getSwitchesInOpenflowDomain(pinSwitch); if (switches == null) { // indicates no links are connected to the switches - switches = new HashSet<Long>(); + switches = new HashSet<DatapathId>(); switches.add(pinSwitch); } - for(long sid: switches) { - IOFSwitch sw = floodlightProvider.getSwitch(sid); + for(DatapathId sid: switches) { + IOFSwitch sw = switchService.getSwitch(sid); if (sw == null) continue; - Collection<Short> enabledPorts = sw.getEnabledPortNumbers(); + Collection<OFPort> enabledPorts = sw.getEnabledPortNumbers(); if (enabledPorts == null) continue; - Set<Short> ports = new HashSet<Short>(); + Set<OFPort> ports = new HashSet<OFPort>(); ports.addAll(enabledPorts); // all the ports known to topology // without tunnels. // out of these, we need to choose only those that are // broadcast port, otherwise, we should eliminate. - Set<Short> portsKnownToTopo = ti.getPortsWithLinks(sid); + Set<OFPort> portsKnownToTopo = ti.getPortsWithLinks(sid); if (portsKnownToTopo != null) { - for(short p: portsKnownToTopo) { + for(OFPort p: portsKnownToTopo) { NodePortTuple npt = new NodePortTuple(sid, p); if (ti.isBroadcastDomainPort(npt) == false) { @@ -1073,7 +1084,7 @@ public class TopologyManager implements } } - Set<Short> portsToEliminate = getPortsToEliminateForBDDP(sid); + Set<OFPort> portsToEliminate = getPortsToEliminateForBDDP(sid); if (portsToEliminate != null) { ports.removeAll(portsToEliminate); } @@ -1084,7 +1095,7 @@ public class TopologyManager implements } // we have all the switch ports to which we need to broadcast. - doMultiActionPacketOut(pi.getPacketData(), sw, ports, cntx); + doMultiActionPacketOut(pi.getData(), sw, ports, cntx); } } @@ -1168,18 +1179,18 @@ public class TopologyManager implements return (Collections.unmodifiableList(appliedUpdates)); } - protected void addOrUpdateSwitch(long sw) { + protected void addOrUpdateSwitch(DatapathId sw) { // nothing to do here for the time being. return; } - public void addTunnelPort(long sw, short port) { + public void addTunnelPort(DatapathId sw, OFPort port) { NodePortTuple npt = new NodePortTuple(sw, port); tunnelPorts.add(npt); tunnelPortsUpdated = true; } - public void removeTunnelPort(long sw, short port) { + public void removeTunnelPort(DatapathId sw, OFPort port) { NodePortTuple npt = new NodePortTuple(sw, port); tunnelPorts.remove(npt); tunnelPortsUpdated = true; @@ -1248,7 +1259,7 @@ public class TopologyManager implements TopologyEventInfo topologyInfo = new TopologyEventInfo(0, nt.getClusters().size(), - new HashMap<Long, List<NodePortTuple>>(), + new HashMap<DatapathId, List<NodePortTuple>>(), 0); evTopology.updateEventWithFlush(new TopologyEvent(reason, topologyInfo)); @@ -1318,27 +1329,27 @@ public class TopologyManager implements public void informListeners(List<LDUpdate> linkUpdates) { - if (role != null && role != Role.MASTER) + if (role != null && role != HARole.ACTIVE) return; - for(int i=0; i<topologyAware.size(); ++i) { + for(int i=0; i < topologyAware.size(); ++i) { ITopologyListener listener = topologyAware.get(i); listener.topologyChanged(linkUpdates); } } - public void addSwitch(long sid) { + public void addSwitch(DatapathId sid) { if (switchPorts.containsKey(sid) == false) { - switchPorts.put(sid, new HashSet<Short>()); + switchPorts.put(sid, new HashSet<OFPort>()); } } - private void addPortToSwitch(long s, short p) { + private void addPortToSwitch(DatapathId s, OFPort p) { addSwitch(s); switchPorts.get(s).add(p); } - public void removeSwitch(long sid) { + public void removeSwitch(DatapathId sid) { // Delete all the links in the switch, switch and all // associated data should be deleted. if (switchPorts.containsKey(sid) == false) return; @@ -1351,7 +1362,7 @@ public class TopologyManager implements } Set<Link> linksToRemove = new HashSet<Link>(); - for(Short p: switchPorts.get(sid)) { + for(OFPort p: switchPorts.get(sid)) { NodePortTuple n1 = new NodePortTuple(sid, p); linksToRemove.addAll(switchPortLinks.get(n1)); } @@ -1414,13 +1425,13 @@ public class TopologyManager implements return result1 || result2; } - protected void addOrUpdateTunnelLink(long srcId, short srcPort, long dstId, - short dstPort) { + protected void addOrUpdateTunnelLink(DatapathId srcId, OFPort srcPort, DatapathId dstId, + OFPort dstPort) { // If you need to handle tunnel links, this is a placeholder. } - public void addOrUpdateLink(long srcId, short srcPort, long dstId, - short dstPort, LinkType type) { + public void addOrUpdateLink(DatapathId srcId, OFPort srcPort, DatapathId dstId, + OFPort dstPort, LinkType type) { Link link = new Link(srcId, srcPort, dstId, dstPort); if (type.equals(LinkType.MULTIHOP_LINK)) { @@ -1477,8 +1488,8 @@ public class TopologyManager implements } } - public void removeLink(long srcId, short srcPort, - long dstId, short dstPort) { + public void removeLink(DatapathId srcId, OFPort srcPort, + DatapathId dstId, OFPort dstPort) { Link link = new Link(srcId, srcPort, dstId, dstPort); removeLink(link); } @@ -1507,7 +1518,7 @@ public class TopologyManager implements /** * Getters. No Setters. */ - public Map<Long, Set<Short>> getSwitchPorts() { + public Map<DatapathId, Set<OFPort>> getSwitchPorts() { return switchPorts; } @@ -1533,15 +1544,15 @@ public class TopologyManager implements * Switch methods */ @Override - public Set<Short> getPorts(long sw) { - IOFSwitch iofSwitch = floodlightProvider.getSwitch(sw); + public Set<OFPort> getPorts(DatapathId sw) { + IOFSwitch iofSwitch = switchService.getSwitch(sw); if (iofSwitch == null) return Collections.emptySet(); - Collection<Short> ofpList = iofSwitch.getEnabledPortNumbers(); + Collection<OFPort> ofpList = iofSwitch.getEnabledPortNumbers(); if (ofpList == null) return Collections.emptySet(); - Set<Short> ports = new HashSet<Short>(ofpList); - Set<Short> qPorts = linkDiscovery.getQuarantinedPorts(sw); + Set<OFPort> ports = new HashSet<OFPort>(ofpList); + Set<OFPort> qPorts = linkDiscovery.getQuarantinedPorts(sw); if (qPorts != null) ports.removeAll(qPorts); diff --git a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java index 75b0b00d3a9fb082e14a18e3da34712fcdee4e36..eb4c368e80b4131d8eff36879cbb5b86564f2ae9 100644 --- a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java +++ b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java @@ -22,9 +22,10 @@ import java.util.Set; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IOFSwitch; +import net.floodlightcontroller.core.LogicalOFMessageCategory; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFType; /** * Dampens OFMessages sent to an OF switch. A message is only written to @@ -134,7 +135,7 @@ public class OFMessageDamper { FloodlightContext cntx, boolean flush) throws IOException { if (! msgTypesToCache.contains(msg.getType())) { - sw.writeThrottled(msg, cntx); + sw.write(msg, LogicalOFMessageCategory.MAIN); if (flush) { sw.flush(); } @@ -146,7 +147,7 @@ public class OFMessageDamper { // entry exists in cache. Dampening. return false; } else { - sw.writeThrottled(msg, cntx); + sw.write(msg, LogicalOFMessageCategory.MAIN); if (flush) { sw.flush(); } diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java index 1d64144dcf19a3d9a73fce36b3976f8b7d4cbaec..258368329d1a5c71023c73c2037e7d59c23c31ab 100644 --- a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java +++ b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java @@ -28,14 +28,14 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.OFMatch; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/openflow/protocol/Instantiable.java b/src/main/java/org/openflow/protocol/Instantiable.java deleted file mode 100644 index 1358ba7526f2b59d7f37ea23e94a723c8e2d2e50..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/Instantiable.java +++ /dev/null @@ -1,31 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface Instantiable<E> { - - /** - * Create a new instance of a given subclass. - * @return the new instance. - */ - public E instantiate(); -} diff --git a/src/main/java/org/openflow/protocol/OFBarrierReply.java b/src/main/java/org/openflow/protocol/OFBarrierReply.java deleted file mode 100644 index a79a15f07918f4db09db438f68f03b048cfc4bf1..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFBarrierReply.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - -/** - * Represents an OFPT_BARRIER_REPLY message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFBarrierReply extends OFMessage { - public OFBarrierReply() { - super(); - this.type = OFType.BARRIER_REPLY; - this.length = U16.t(OFMessage.MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFBarrierRequest.java b/src/main/java/org/openflow/protocol/OFBarrierRequest.java deleted file mode 100644 index 999218636550dac8af837f95a69480a3b596aa02..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFBarrierRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - -/** - * Represents an OFPT_BARRIER_REQUEST message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFBarrierRequest extends OFMessage { - public OFBarrierRequest() { - super(); - this.type = OFType.BARRIER_REQUEST; - this.length = U16.t(OFMessage.MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFEchoReply.java b/src/main/java/org/openflow/protocol/OFEchoReply.java deleted file mode 100644 index 3e282a74a052e5dcb1792e40d2402e1352555244..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFEchoReply.java +++ /dev/null @@ -1,36 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - -/** - * Represents an ofp_echo_reply message - * - * @author Rob Sherwood (rob.sherwood@stanford.edu) - */ - -public class OFEchoReply extends OFEchoRequest { - public static int MINIMUM_LENGTH = 8; - - public OFEchoReply() { - super(); - this.type = OFType.ECHO_REPLY; - this.length = U16.t(MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFEchoRequest.java b/src/main/java/org/openflow/protocol/OFEchoRequest.java deleted file mode 100644 index 295a3972e8a29d5ed928150d2076ac6d6e16fd52..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFEchoRequest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents an ofp_echo_request message - * - * @author Rob Sherwood (rob.sherwood@stanford.edu) - */ - -public class OFEchoRequest extends OFMessage { - public static int MINIMUM_LENGTH = 8; - byte[] payload; - - public OFEchoRequest() { - super(); - this.type = OFType.ECHO_REQUEST; - this.length = U16.t(MINIMUM_LENGTH); - } - - @Override - public void readFrom(ChannelBuffer bb) { - super.readFrom(bb); - int datalen = this.getLengthU() - MINIMUM_LENGTH; - if (datalen > 0) { - this.payload = new byte[datalen]; - bb.readBytes(payload); - } - } - - /** - * @return the payload - */ - public byte[] getPayload() { - return payload; - } - - /** - * @param payload - * the payload to set - */ - public void setPayload(byte[] payload) { - this.payload = payload; - } - - @Override - public void writeTo(ChannelBuffer bb) { - super.writeTo(bb); - if (payload != null) - bb.writeBytes(payload); - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(payload); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - OFEchoRequest other = (OFEchoRequest) obj; - if (!Arrays.equals(payload, other.payload)) - return false; - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFError.java b/src/main/java/org/openflow/protocol/OFError.java deleted file mode 100644 index df7b236024c9370d43c5f28392548319cd83f7ce..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFError.java +++ /dev/null @@ -1,325 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.Arrays; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.factory.MessageParseException; -import org.openflow.protocol.factory.OFMessageFactory; -import org.openflow.protocol.factory.OFMessageFactoryAware; -import org.openflow.util.U16; - -/** - * Represents an ofp_error_msg - * - * @author David Erickson (daviderickson@cs.stanford.edu) - * @author Rob Sherwood (rob.sherwood@stanford.edu) - */ -public class OFError extends OFMessage implements OFMessageFactoryAware { - public static int MINIMUM_LENGTH = 12; - - public enum OFErrorType { - // OFPET_VENDOR_ERROR is an extension that was added in Open vSwitch and isn't - // in the OF 1.0 spec, but it was easier to add it here instead of adding - // generic support for extensible vendor-defined error messages. - // It uses the random value 0xb0c2 to avoid conflicts with other possible new - // error types. Support for vendor-defined extended errors has been standardized - // in the OF 1.2 spec, so this workaround is only needed for 1.0. - OFPET_HELLO_FAILED, OFPET_BAD_REQUEST, OFPET_BAD_ACTION, OFPET_FLOW_MOD_FAILED, OFPET_PORT_MOD_FAILED, OFPET_QUEUE_OP_FAILED, OFPET_VENDOR_ERROR((short)0xb0c2); - - protected short value; - - private OFErrorType() { - this.value = (short) this.ordinal(); - } - - private OFErrorType(short value) { - this.value = value; - } - - public short getValue() { - return value; - } - } - - public enum OFHelloFailedCode { - OFPHFC_INCOMPATIBLE, OFPHFC_EPERM - } - - public enum OFBadRequestCode { - OFPBRC_BAD_VERSION, OFPBRC_BAD_TYPE, OFPBRC_BAD_STAT, OFPBRC_BAD_VENDOR, OFPBRC_BAD_SUBTYPE, OFPBRC_EPERM, OFPBRC_BAD_LEN, OFPBRC_BUFFER_EMPTY, OFPBRC_BUFFER_UNKNOWN - } - - public enum OFBadActionCode { - OFPBAC_BAD_TYPE, OFPBAC_BAD_LEN, OFPBAC_BAD_VENDOR, OFPBAC_BAD_VENDOR_TYPE, OFPBAC_BAD_OUT_PORT, OFPBAC_BAD_ARGUMENT, OFPBAC_EPERM, OFPBAC_TOO_MANY, OFPBAC_BAD_QUEUE - } - - public enum OFFlowModFailedCode { - OFPFMFC_ALL_TABLES_FULL, OFPFMFC_OVERLAP, OFPFMFC_EPERM, OFPFMFC_BAD_EMERG_TIMEOUT, OFPFMFC_BAD_COMMAND, OFPFMFC_UNSUPPORTED - } - - public enum OFPortModFailedCode { - OFPPMFC_BAD_PORT, OFPPMFC_BAD_HW_ADDR - } - - public enum OFQueueOpFailedCode { - OFPQOFC_BAD_PORT, OFPQOFC_BAD_QUEUE, OFPQOFC_EPERM - } - - protected short errorType; - protected short errorCode; - protected int vendor; - protected int vendorErrorType; - protected short vendorErrorCode; - protected OFMessageFactory factory; - protected byte[] error; - protected boolean errorIsAscii; - - public OFError() { - super(); - this.type = OFType.ERROR; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** convenience constructor */ - public OFError(OFErrorType errorType) { - this(); - setErrorType(errorType); - } - - /** - * @return the errorType - */ - public short getErrorType() { - return errorType; - } - - /** - * @param errorType - * the errorType to set - */ - public void setErrorType(short errorType) { - this.errorType = errorType; - } - - public void setErrorType(OFErrorType type) { - this.errorType = type.getValue(); - } - - /** - * @return true if the error is an extended vendor error - */ - public boolean isVendorError() { - return errorType == OFErrorType.OFPET_VENDOR_ERROR.getValue(); - } - - /** - * @return the errorCode - */ - public short getErrorCode() { - return errorCode; - } - - /** - * @param errorCode - * the errorCode to set - */ - public void setErrorCode(OFHelloFailedCode code) { - this.errorCode = (short) code.ordinal(); - } - - public void setErrorCode(short errorCode) { - this.errorCode = errorCode; - } - - public void setErrorCode(OFBadRequestCode code) { - this.errorCode = (short) code.ordinal(); - } - - public void setErrorCode(OFBadActionCode code) { - this.errorCode = (short) code.ordinal(); - } - - public void setErrorCode(OFFlowModFailedCode code) { - this.errorCode = (short) code.ordinal(); - } - - public void setErrorCode(OFPortModFailedCode code) { - this.errorCode = (short) code.ordinal(); - } - - public void setErrorCode(OFQueueOpFailedCode code) { - this.errorCode = (short) code.ordinal(); - } - - public int getVendorErrorType() { - return vendorErrorType; - } - - public void setVendorErrorType(int vendorErrorType) { - this.vendorErrorType = vendorErrorType; - } - - public short getVendorErrorCode() { - return vendorErrorCode; - } - - public void setVendorErrorCode(short vendorErrorCode) { - this.vendorErrorCode = vendorErrorCode; - } - - public OFMessage getOffendingMsg() throws MessageParseException { - // should only have one message embedded; if more than one, just - // grab first - if (this.error == null) - return null; - ChannelBuffer errorMsg = ChannelBuffers.wrappedBuffer(this.error); - if (factory == null) - throw new RuntimeException("MessageFactory not set"); - - List<OFMessage> msglist = this.factory.parseMessage(errorMsg); - if (msglist == null) - return null; - return msglist.get(0); - } - - /** - * Write this offending message into the payload of the Error message - * - * @param offendingMsg - */ - - public void setOffendingMsg(OFMessage offendingMsg) { - if (offendingMsg == null) { - super.setLengthU(MINIMUM_LENGTH); - } else { - this.error = new byte[offendingMsg.getLengthU()]; - ChannelBuffer data = ChannelBuffers.wrappedBuffer(this.error); - data.writerIndex(0); - offendingMsg.writeTo(data); - super.setLengthU(MINIMUM_LENGTH + offendingMsg.getLengthU()); - } - } - - public OFMessageFactory getFactory() { - return factory; - } - - @Override - public void setMessageFactory(OFMessageFactory factory) { - this.factory = factory; - } - - /** - * @return the error - */ - public byte[] getError() { - return error; - } - - /** - * @param error - * the error to set - */ - public void setError(byte[] error) { - this.error = error; - } - - /** - * @return the errorIsAscii - */ - public boolean isErrorIsAscii() { - return errorIsAscii; - } - - /** - * @param errorIsAscii - * the errorIsAscii to set - */ - public void setErrorIsAscii(boolean errorIsAscii) { - this.errorIsAscii = errorIsAscii; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.errorType = data.readShort(); - this.errorCode = data.readShort(); - int dataLength = this.getLengthU() - MINIMUM_LENGTH; - if (dataLength > 0) { - this.error = new byte[dataLength]; - data.readBytes(this.error); - if (this.errorType == OFErrorType.OFPET_HELLO_FAILED.getValue()) - this.errorIsAscii = true; - } - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(errorType); - data.writeShort(errorCode); - if (error != null) - data.writeBytes(error); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(error); - result = prime * result + errorCode; - result = prime * result + (errorIsAscii ? 1231 : 1237); - result = prime * result + errorType; - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - OFError other = (OFError) obj; - if (!Arrays.equals(error, other.error)) - return false; - if (errorCode != other.errorCode) - return false; - if (errorIsAscii != other.errorIsAscii) - return false; - if (errorType != other.errorType) - return false; - return true; - } - -} diff --git a/src/main/java/org/openflow/protocol/OFFeaturesReply.java b/src/main/java/org/openflow/protocol/OFFeaturesReply.java deleted file mode 100644 index 7c2cc51cf21dca6c83978dc1d995deb5ba0d4421..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFFeaturesReply.java +++ /dev/null @@ -1,261 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.ArrayList; -import java.util.List; - - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.serializers.OFFeaturesReplyJSONSerializer; -import org.openflow.protocol.serializers.StringDpidToLongJSONDeserializer; -import org.openflow.util.U16; - - -/** - * Represents a features reply message - * @author David Erickson (daviderickson@cs.stanford.edu) - * - */ -@JsonSerialize(using=OFFeaturesReplyJSONSerializer.class) -public class OFFeaturesReply extends OFMessage { - public static int MINIMUM_LENGTH = 32; - - /** - * Corresponds to bits on the capabilities field - */ - public enum OFCapabilities { - OFPC_FLOW_STATS (1 << 0), - OFPC_TABLE_STATS (1 << 1), - OFPC_PORT_STATS (1 << 2), - OFPC_STP (1 << 3), - OFPC_RESERVED (1 << 4), - OFPC_IP_REASM (1 << 5), - OFPC_QUEUE_STATS (1 << 6), - OFPC_ARP_MATCH_IP (1 << 7); - - protected int value; - - private OFCapabilities(int value) { - this.value = value; - } - - /** - * @return the value - */ - public int getValue() { - return value; - } - } - - protected long datapathId; - protected int buffers; - protected byte tables; - protected int capabilities; - protected int actions; - protected List<OFPhysicalPort> ports; - - public OFFeaturesReply() { - super(); - this.type = OFType.FEATURES_REPLY; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * @return the datapathId - */ - public long getDatapathId() { - return datapathId; - } - - /** - * @param datapathId the datapathId to set - */ - @JsonDeserialize(using=StringDpidToLongJSONDeserializer.class) - public void setDatapathId(long datapathId) { - this.datapathId = datapathId; - } - - /** - * @return the buffers - */ - public int getBuffers() { - return buffers; - } - - /** - * @param buffers the buffers to set - */ - public void setBuffers(int buffers) { - this.buffers = buffers; - } - - /** - * @return the tables - */ - public byte getTables() { - return tables; - } - - /** - * @param tables the tables to set - */ - public void setTables(byte tables) { - this.tables = tables; - } - - /** - * @return the capabilities - */ - public int getCapabilities() { - return capabilities; - } - - /** - * @param capabilities the capabilities to set - */ - public void setCapabilities(int capabilities) { - this.capabilities = capabilities; - } - - /** - * @return the actions - */ - public int getActions() { - return actions; - } - - /** - * @param actions the actions to set - */ - public void setActions(int actions) { - this.actions = actions; - } - - /** - * @return the ports - */ - public List<OFPhysicalPort> getPorts() { - return ports; - } - - /** - * @param ports the ports to set - */ - public void setPorts(List<OFPhysicalPort> ports) { - this.ports = ports; - if (ports == null) { - this.setLengthU(MINIMUM_LENGTH); - } else { - this.setLengthU(MINIMUM_LENGTH + ports.size() - * OFPhysicalPort.MINIMUM_LENGTH); - } - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.datapathId = data.readLong(); - this.buffers = data.readInt(); - this.tables = data.readByte(); - data.readerIndex(data.readerIndex() + 3); // pad - this.capabilities = data.readInt(); - this.actions = data.readInt(); - if (this.ports == null) { - this.ports = new ArrayList<OFPhysicalPort>(); - } else { - this.ports.clear(); - } - int portCount = (super.getLengthU() - 32) - / OFPhysicalPort.MINIMUM_LENGTH; - OFPhysicalPort port; - for (int i = 0; i < portCount; ++i) { - port = new OFPhysicalPort(); - port.readFrom(data); - this.ports.add(port); - } - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeLong(this.datapathId); - data.writeInt(this.buffers); - data.writeByte(this.tables); - data.writeShort((short) 0); // pad - data.writeByte((byte) 0); // pad - data.writeInt(this.capabilities); - data.writeInt(this.actions); - if (this.ports != null) - for (OFPhysicalPort port : this.ports) { - port.writeTo(data); - } - } - - @Override - public int hashCode() { - final int prime = 139; - int result = super.hashCode(); - result = prime * result + actions; - result = prime * result + buffers; - result = prime * result + capabilities; - result = prime * result + (int) (datapathId ^ (datapathId >>> 32)); - result = prime * result + ((ports == null) ? 0 : ports.hashCode()); - result = prime * result + tables; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFFeaturesReply)) { - return false; - } - OFFeaturesReply other = (OFFeaturesReply) obj; - if (actions != other.actions) { - return false; - } - if (buffers != other.buffers) { - return false; - } - if (capabilities != other.capabilities) { - return false; - } - if (datapathId != other.datapathId) { - return false; - } - if (ports == null) { - if (other.ports != null) { - return false; - } - } else if (!ports.equals(other.ports)) { - return false; - } - if (tables != other.tables) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFFeaturesRequest.java b/src/main/java/org/openflow/protocol/OFFeaturesRequest.java deleted file mode 100644 index 0a89e4f57f1559afcbc751cb80d9f9fb10700a93..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFFeaturesRequest.java +++ /dev/null @@ -1,36 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - - -/** - * Represents a features request message - * @author David Erickson (daviderickson@cs.stanford.edu) - * - */ -public class OFFeaturesRequest extends OFMessage { - public static int MINIMUM_LENGTH = 8; - - public OFFeaturesRequest() { - super(); - this.type = OFType.FEATURES_REQUEST; - this.length = U16.t(MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFFlowMod.java b/src/main/java/org/openflow/protocol/OFFlowMod.java deleted file mode 100644 index 0d2aad2157d4bfcbf19572bb943d5fb026c6cbb7..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFFlowMod.java +++ /dev/null @@ -1,389 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.LinkedList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.factory.OFActionFactory; -import org.openflow.protocol.factory.OFActionFactoryAware; -import org.openflow.util.U16; - -/** - * Represents an ofp_flow_mod message - * @author David Erickson (daviderickson@cs.stanford.edu) - * - */ -public class OFFlowMod extends OFMessage implements OFActionFactoryAware, Cloneable { - public static int MINIMUM_LENGTH = 72; - - public static final short OFPFC_ADD = 0; /* New flow. */ - public static final short OFPFC_MODIFY = 1; /* Modify all matching flows. */ - public static final short OFPFC_MODIFY_STRICT = 2; /* Modify entry strictly matching wildcards */ - public static final short OFPFC_DELETE=3; /* Delete all matching flows. */ - public static final short OFPFC_DELETE_STRICT =4; /* Strictly match wildcards and priority. */ - - // Open Flow Flow Mod Flags. Use "or" operation to set multiple flags - public static final short OFPFF_SEND_FLOW_REM = 0x1; // 1 << 0 - public static final short OFPFF_CHECK_OVERLAP = 0x2; // 1 << 1 - public static final short OFPFF_EMERG = 0x4; // 1 << 2 - - protected OFActionFactory actionFactory; - protected OFMatch match; - protected long cookie; - protected short command; - protected short idleTimeout; - protected short hardTimeout; - protected short priority; - protected int bufferId; - protected short outPort; - protected short flags; - protected List<OFAction> actions; - - public OFFlowMod() { - super(); - this.outPort = OFPort.OFPP_NONE.getValue(); - this.type = OFType.FLOW_MOD; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * Get buffer_id - * @return - */ - public int getBufferId() { - return this.bufferId; - } - - /** - * Set buffer_id - * @param bufferId - */ - public OFFlowMod setBufferId(int bufferId) { - this.bufferId = bufferId; - return this; - } - - /** - * Get cookie - * @return - */ - public long getCookie() { - return this.cookie; - } - - /** - * Set cookie - * @param cookie - */ - public OFFlowMod setCookie(long cookie) { - this.cookie = cookie; - return this; - } - - /** - * Get command - * @return - */ - public short getCommand() { - return this.command; - } - - /** - * Set command - * @param command - */ - public OFFlowMod setCommand(short command) { - this.command = command; - return this; - } - - /** - * Get flags - * @return - */ - public short getFlags() { - return this.flags; - } - - /** - * Set flags - * @param flags - */ - public OFFlowMod setFlags(short flags) { - this.flags = flags; - return this; - } - - /** - * Get hard_timeout - * @return - */ - public short getHardTimeout() { - return this.hardTimeout; - } - - /** - * Set hard_timeout - * @param hardTimeout - */ - public OFFlowMod setHardTimeout(short hardTimeout) { - this.hardTimeout = hardTimeout; - return this; - } - - /** - * Get idle_timeout - * @return - */ - public short getIdleTimeout() { - return this.idleTimeout; - } - - /** - * Set idle_timeout - * @param idleTimeout - */ - public OFFlowMod setIdleTimeout(short idleTimeout) { - this.idleTimeout = idleTimeout; - return this; - } - - /** - * Gets a copy of the OFMatch object for this FlowMod, changes to this - * object do not modify the FlowMod - * @return - */ - public OFMatch getMatch() { - return this.match; - } - - /** - * Set match - * @param match - */ - public OFFlowMod setMatch(OFMatch match) { - this.match = match; - return this; - } - - /** - * Get out_port - * @return - */ - public short getOutPort() { - return this.outPort; - } - - /** - * Set out_port - * @param outPort - */ - public OFFlowMod setOutPort(short outPort) { - this.outPort = outPort; - return this; - } - - /** - * Set out_port - * @param port - */ - public OFFlowMod setOutPort(OFPort port) { - this.outPort = port.getValue(); - return this; - } - - /** - * Get priority - * @return - */ - public short getPriority() { - return this.priority; - } - - /** - * Set priority - * @param priority - */ - public OFFlowMod setPriority(short priority) { - this.priority = priority; - return this; - } - - /** - * Returns read-only copies of the actions contained in this Flow Mod - * @return a list of ordered OFAction objects - */ - public List<OFAction> getActions() { - return this.actions; - } - - /** - * Sets the list of actions this Flow Mod contains - * @param actions a list of ordered OFAction objects - */ - public OFFlowMod setActions(List<OFAction> actions) { - this.actions = actions; - return this; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - if (this.match == null) - this.match = new OFMatch(); - this.match.readFrom(data); - this.cookie = data.readLong(); - this.command = data.readShort(); - this.idleTimeout = data.readShort(); - this.hardTimeout = data.readShort(); - this.priority = data.readShort(); - this.bufferId = data.readInt(); - this.outPort = data.readShort(); - this.flags = data.readShort(); - if (this.actionFactory == null) - throw new RuntimeException("OFActionFactory not set"); - this.actions = this.actionFactory.parseActions(data, getLengthU() - - MINIMUM_LENGTH); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - this.match.writeTo(data); - data.writeLong(cookie); - data.writeShort(command); - data.writeShort(idleTimeout); - data.writeShort(hardTimeout); - data.writeShort(priority); - data.writeInt(bufferId); - data.writeShort(outPort); - data.writeShort(flags); - if (actions != null) { - for (OFAction action : actions) { - action.writeTo(data); - } - } - } - - @Override - public void setActionFactory(OFActionFactory actionFactory) { - this.actionFactory = actionFactory; - } - - @Override - public int hashCode() { - final int prime = 227; - int result = super.hashCode(); - result = prime * result + ((actions == null) ? 0 : actions.hashCode()); - result = prime * result + bufferId; - result = prime * result + command; - result = prime * result + (int) (cookie ^ (cookie >>> 32)); - result = prime * result + flags; - result = prime * result + hardTimeout; - result = prime * result + idleTimeout; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime * result + outPort; - result = prime * result + priority; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFFlowMod)) { - return false; - } - OFFlowMod other = (OFFlowMod) obj; - if (actions == null) { - if (other.actions != null) { - return false; - } - } else if (!actions.equals(other.actions)) { - return false; - } - if (bufferId != other.bufferId) { - return false; - } - if (command != other.command) { - return false; - } - if (cookie != other.cookie) { - return false; - } - if (flags != other.flags) { - return false; - } - if (hardTimeout != other.hardTimeout) { - return false; - } - if (idleTimeout != other.idleTimeout) { - return false; - } - if (match == null) { - if (other.match != null) { - return false; - } - } else if (!match.equals(other.match)) { - return false; - } - if (outPort != other.outPort) { - return false; - } - if (priority != other.priority) { - return false; - } - return true; - } - - /* (non-Javadoc) - * @see java.lang.Object#clone() - */ - @Override - public OFFlowMod clone() throws CloneNotSupportedException { - OFMatch neoMatch = match.clone(); - OFFlowMod flowMod= (OFFlowMod) super.clone(); - flowMod.setMatch(neoMatch); - List<OFAction> neoActions = new LinkedList<OFAction>(); - for(OFAction action: this.actions) - neoActions.add(action.clone()); - flowMod.setActions(neoActions); - return flowMod; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "OFFlowMod [actionFactory=" + actionFactory + ", actions=" - + actions + ", bufferId=" + bufferId + ", command=" + command - + ", cookie=" + Long.toHexString(cookie) + ", flags=" + flags + ", hardTimeout=" - + hardTimeout + ", idleTimeout=" + idleTimeout + ", match=" - + match + ", outPort=" + outPort + ", priority=" + priority - + ", length=" + length + ", type=" + type + ", version=" - + version + ", xid=" + xid + "]"; - } -} diff --git a/src/main/java/org/openflow/protocol/OFFlowRemoved.java b/src/main/java/org/openflow/protocol/OFFlowRemoved.java deleted file mode 100644 index cfe2e14ce34691a6b6b096c181cfd67fa5c214aa..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFFlowRemoved.java +++ /dev/null @@ -1,294 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents an ofp_flow_removed message - * @author David Erickson (daviderickson@cs.stanford.edu) - * - */ -public class OFFlowRemoved extends OFMessage { - public static int MINIMUM_LENGTH = 88; - - public enum OFFlowRemovedReason { - OFPRR_IDLE_TIMEOUT, - OFPRR_HARD_TIMEOUT, - OFPRR_DELETE - } - - protected OFMatch match; - protected long cookie; - protected short priority; - protected OFFlowRemovedReason reason; - protected int durationSeconds; - protected int durationNanoseconds; - protected short idleTimeout; - protected long packetCount; - protected long byteCount; - - public OFFlowRemoved() { - super(); - this.type = OFType.FLOW_REMOVED; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * Get cookie - * @return - */ - public long getCookie() { - return this.cookie; - } - - /** - * Set cookie - * @param cookie - */ - public void setCookie(long cookie) { - this.cookie = cookie; - } - - /** - * Get idle_timeout - * @return - */ - public short getIdleTimeout() { - return this.idleTimeout; - } - - /** - * Set idle_timeout - * @param idleTimeout - */ - public void setIdleTimeout(short idleTimeout) { - this.idleTimeout = idleTimeout; - } - - /** - * Gets a copy of the OFMatch object for this FlowMod, changes to this - * object do not modify the FlowMod - * @return - */ - public OFMatch getMatch() { - return this.match; - } - - /** - * Set match - * @param match - */ - public void setMatch(OFMatch match) { - this.match = match; - } - - /** - * Get priority - * @return - */ - public short getPriority() { - return this.priority; - } - - /** - * Set priority - * @param priority - */ - public void setPriority(short priority) { - this.priority = priority; - } - - /** - * @return the reason - */ - public OFFlowRemovedReason getReason() { - return reason; - } - - /** - * @param reason the reason to set - */ - public void setReason(OFFlowRemovedReason reason) { - this.reason = reason; - } - - /** - * @return the durationSeconds - */ - public int getDurationSeconds() { - return durationSeconds; - } - - /** - * @param durationSeconds the durationSeconds to set - */ - public void setDurationSeconds(int durationSeconds) { - this.durationSeconds = durationSeconds; - } - - /** - * @return the durationNanoseconds - */ - public int getDurationNanoseconds() { - return durationNanoseconds; - } - - /** - * @param durationNanoseconds the durationNanoseconds to set - */ - public void setDurationNanoseconds(int durationNanoseconds) { - this.durationNanoseconds = durationNanoseconds; - } - - /** - * @return the packetCount - */ - public long getPacketCount() { - return packetCount; - } - - /** - * @param packetCount the packetCount to set - */ - public void setPacketCount(long packetCount) { - this.packetCount = packetCount; - } - - /** - * @return the byteCount - */ - public long getByteCount() { - return byteCount; - } - - /** - * @param byteCount the byteCount to set - */ - public void setByteCount(long byteCount) { - this.byteCount = byteCount; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - if (this.match == null) - this.match = new OFMatch(); - this.match.readFrom(data); - this.cookie = data.readLong(); - this.priority = data.readShort(); - int reasonIndex = 0xff & data.readByte(); - if (reasonIndex >= OFFlowRemovedReason.values().length) { - reasonIndex = OFFlowRemovedReason.values().length - 1; - } - this.reason = OFFlowRemovedReason.values()[reasonIndex]; - data.readByte(); // pad - this.durationSeconds = data.readInt(); - this.durationNanoseconds = data.readInt(); - this.idleTimeout = data.readShort(); - data.readByte(); // pad - data.readByte(); // pad - this.packetCount = data.readLong(); - this.byteCount = data.readLong(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - this.match.writeTo(data); - data.writeLong(cookie); - data.writeShort(priority); - data.writeByte((byte) this.reason.ordinal()); - data.writeByte((byte) 0); - data.writeInt(this.durationSeconds); - data.writeInt(this.durationNanoseconds); - data.writeShort(idleTimeout); - data.writeByte((byte) 0); // pad - data.writeByte((byte) 0); // pad - data.writeLong(this.packetCount); - data.writeLong(this.byteCount); - } - - @Override - public int hashCode() { - final int prime = 271; - int result = super.hashCode(); - result = prime * result + (int) (byteCount ^ (byteCount >>> 32)); - result = prime * result + (int) (cookie ^ (cookie >>> 32)); - result = prime * result + durationNanoseconds; - result = prime * result + durationSeconds; - result = prime * result + idleTimeout; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime * result + (int) (packetCount ^ (packetCount >>> 32)); - result = prime * result + priority; - result = prime * result + ((reason == null) ? 0 : reason.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFFlowRemoved)) { - return false; - } - OFFlowRemoved other = (OFFlowRemoved) obj; - if (byteCount != other.byteCount) { - return false; - } - if (cookie != other.cookie) { - return false; - } - if (durationNanoseconds != other.durationNanoseconds) { - return false; - } - if (durationSeconds != other.durationSeconds) { - return false; - } - if (idleTimeout != other.idleTimeout) { - return false; - } - if (match == null) { - if (other.match != null) { - return false; - } - } else if (!match.equals(other.match)) { - return false; - } - if (packetCount != other.packetCount) { - return false; - } - if (priority != other.priority) { - return false; - } - if (reason == null) { - if (other.reason != null) { - return false; - } - } else if (!reason.equals(other.reason)) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFGetConfigReply.java b/src/main/java/org/openflow/protocol/OFGetConfigReply.java deleted file mode 100644 index 257867afa521eb4b1c753c1e98c03e5433e8cdab..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFGetConfigReply.java +++ /dev/null @@ -1,29 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -/** - * Represents an OFPT_GET_CONFIG_REPLY type message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFGetConfigReply extends OFSwitchConfig { - public OFGetConfigReply() { - super(); - this.type = OFType.GET_CONFIG_REPLY; - } -} diff --git a/src/main/java/org/openflow/protocol/OFGetConfigRequest.java b/src/main/java/org/openflow/protocol/OFGetConfigRequest.java deleted file mode 100644 index 85c7499243fc73d4c31aa4b0035e9a3353662f89..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFGetConfigRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - -/** - * Represents an OFPT_GET_CONFIG_REQUEST type message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFGetConfigRequest extends OFMessage { - public OFGetConfigRequest() { - super(); - this.type = OFType.GET_CONFIG_REQUEST; - this.length = U16.t(OFMessage.MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFHello.java b/src/main/java/org/openflow/protocol/OFHello.java deleted file mode 100644 index e702ca4d98d986da7b3176bda07abaefe07e2145..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFHello.java +++ /dev/null @@ -1,39 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - - -/** - * Represents an ofp_hello message - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 8, 2010 - */ -public class OFHello extends OFMessage { - public static int MINIMUM_LENGTH = 8; - - /** - * Construct a ofp_hello message - */ - public OFHello() { - super(); - this.type = OFType.HELLO; - this.length = U16.t(MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFMatch.java b/src/main/java/org/openflow/protocol/OFMatch.java deleted file mode 100644 index 8c3c9f495bb300567d2fac10ad76e8d3fe097df6..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFMatch.java +++ /dev/null @@ -1,1145 +0,0 @@ -/** - * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior - * University - * - * 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 org.openflow.protocol; - -import java.io.Serializable; -import java.nio.ByteBuffer; -import java.util.Arrays; - -import net.floodlightcontroller.packet.Ethernet; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.serializers.OFMatchJSONSerializer; -import org.openflow.util.HexString; -import org.openflow.util.U16; -import org.openflow.util.U8; - -/** - * Represents an ofp_match structure - * - * @author David Erickson (daviderickson@cs.stanford.edu) - * @author Rob Sherwood (rob.sherwood@stanford.edu) - */ -@JsonSerialize(using = OFMatchJSONSerializer.class) -public class OFMatch implements Cloneable, Serializable { - - /** - * - */ - private static final long serialVersionUID = 1L; - public static int MINIMUM_LENGTH = 40; - final public static int OFPFW_ALL = ((1 << 22) - 1); - - final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */ - final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */ - final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */ - final public static int OFPFW_DL_DST = 1 << 3; /* - * Ethernet destination - * address. - */ - final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */ - final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */ - final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */ - final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */ - - /* - * IP source address wildcard bit count. 0 is exact match, 1 ignores the - * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard - * the entire field. This is the *opposite* of the usual convention where - * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded. - */ - final public static int OFPFW_NW_SRC_SHIFT = 8; - final public static int OFPFW_NW_SRC_BITS = 6; - final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT; - final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT; - - /* IP destination address wildcard bit count. Same format as source. */ - final public static int OFPFW_NW_DST_SHIFT = 14; - final public static int OFPFW_NW_DST_BITS = 6; - final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT; - final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT; - - final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */ - final public static int OFPFW_NW_TOS = 1 << 21; /* - * IP ToS (DSCP field, 6 - * bits). - */ - - final public static int OFPFW_ALL_SANITIZED = (((1 << 22) - 1) - & ~OFPFW_NW_SRC_MASK & ~OFPFW_NW_DST_MASK) - | OFPFW_NW_SRC_ALL - | OFPFW_NW_DST_ALL; - - /* List of Strings for marshalling and unmarshalling to human readable forms */ - final public static String STR_IN_PORT = "in_port"; - final public static String STR_DL_DST = "dl_dst"; - final public static String STR_DL_SRC = "dl_src"; - final public static String STR_DL_TYPE = "dl_type"; - final public static String STR_DL_VLAN = "dl_vlan"; - final public static String STR_DL_VLAN_PCP = "dl_vlan_pcp"; - final public static String STR_NW_DST = "nw_dst"; - final public static String STR_NW_SRC = "nw_src"; - final public static String STR_NW_PROTO = "nw_proto"; - final public static String STR_NW_TOS = "nw_tos"; - final public static String STR_TP_DST = "tp_dst"; - final public static String STR_TP_SRC = "tp_src"; - - protected int wildcards; - protected short inputPort; - protected byte[] dataLayerSource; - protected byte[] dataLayerDestination; - protected short dataLayerVirtualLan; - protected byte dataLayerVirtualLanPriorityCodePoint; - protected short dataLayerType; - protected byte networkTypeOfService; - protected byte networkProtocol; - protected int networkSource; - protected int networkDestination; - protected short transportSource; - protected short transportDestination; - - /** - * By default, create a OFMatch that matches everything (mostly because it's - * the least amount of work to make a valid OFMatch) - */ - public OFMatch() { - this.wildcards = OFPFW_ALL; - this.dataLayerDestination = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0 }; - this.dataLayerSource = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - this.dataLayerVirtualLan = Ethernet.VLAN_UNTAGGED; - this.dataLayerVirtualLanPriorityCodePoint = 0; - this.dataLayerType = 0; - this.inputPort = 0; - this.networkProtocol = 0; - this.networkTypeOfService = 0; - this.networkSource = 0; - this.networkDestination = 0; - this.transportDestination = 0; - this.transportSource = 0; - } - - /** - * Get dl_dst - * - * @return an arrays of bytes - */ - public byte[] getDataLayerDestination() { - return this.dataLayerDestination; - } - - /** - * Set dl_dst - * - * @param dataLayerDestination - */ - public OFMatch setDataLayerDestination(byte[] dataLayerDestination) { - this.dataLayerDestination = dataLayerDestination; - return this; - } - - /** - * Set dl_dst, but first translate to byte[] using HexString - * - * @param mac - * A colon separated string of 6 pairs of octets, e..g., - * "00:17:42:EF:CD:8D" - */ - public OFMatch setDataLayerDestination(String mac) { - byte bytes[] = HexString.fromHexString(mac); - if (bytes.length != 6) - throw new IllegalArgumentException( - "expected string with 6 octets, got '" - + mac - + "'"); - this.dataLayerDestination = bytes; - return this; - } - - /** - * Get dl_src - * - * @return an array of bytes - */ - public byte[] getDataLayerSource() { - return this.dataLayerSource; - } - - /** - * Set dl_src - * - * @param dataLayerSource - */ - public OFMatch setDataLayerSource(byte[] dataLayerSource) { - this.dataLayerSource = dataLayerSource; - return this; - } - - /** - * Set dl_src, but first translate to byte[] using HexString - * - * @param mac - * A colon separated string of 6 pairs of octets, e..g., - * "00:17:42:EF:CD:8D" - */ - public OFMatch setDataLayerSource(String mac) { - byte bytes[] = HexString.fromHexString(mac); - if (bytes.length != 6) - throw new IllegalArgumentException( - "expected string with 6 octets, got '" - + mac - + "'"); - this.dataLayerSource = bytes; - return this; - } - - /** - * Get dl_type - * - * @return ether_type - */ - public short getDataLayerType() { - return this.dataLayerType; - } - - /** - * Set dl_type - * - * @param dataLayerType - */ - public OFMatch setDataLayerType(short dataLayerType) { - this.dataLayerType = dataLayerType; - return this; - } - - /** - * Get dl_vlan - * - * @return vlan tag; VLAN_NONE == no tag - */ - public short getDataLayerVirtualLan() { - return this.dataLayerVirtualLan; - } - - /** - * Set dl_vlan - * - * @param dataLayerVirtualLan - */ - public OFMatch setDataLayerVirtualLan(short dataLayerVirtualLan) { - this.dataLayerVirtualLan = dataLayerVirtualLan; - return this; - } - - /** - * Get dl_vlan_pcp - * - * @return - */ - public byte getDataLayerVirtualLanPriorityCodePoint() { - return this.dataLayerVirtualLanPriorityCodePoint; - } - - /** - * Set dl_vlan_pcp - * - * @param pcp - */ - public OFMatch setDataLayerVirtualLanPriorityCodePoint(byte pcp) { - this.dataLayerVirtualLanPriorityCodePoint = pcp; - return this; - } - - /** - * Get in_port - * - * @return - */ - public short getInputPort() { - return this.inputPort; - } - - /** - * Set in_port - * - * @param inputPort - */ - public OFMatch setInputPort(short inputPort) { - this.inputPort = inputPort; - return this; - } - - /** - * Get nw_dst - * - * @return - */ - public int getNetworkDestination() { - return this.networkDestination; - } - - /** - * Set nw_dst - * - * @param networkDestination - */ - public OFMatch setNetworkDestination(int networkDestination) { - this.networkDestination = networkDestination; - return this; - } - - /** - * Parse this match's wildcard fields and return the number of significant - * bits in the IP destination field. NOTE: this returns the number of bits - * that are fixed, i.e., like CIDR, not the number of bits that are free - * like OpenFlow encodes. - * - * @return a number between 0 (matches all IPs) and 63 ( 32>= implies exact - * match) - */ - public int getNetworkDestinationMaskLen() { - return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT), - 0); - } - - /** - * Parse this match's wildcard fields and return the number of significant - * bits in the IP destination field. NOTE: this returns the number of bits - * that are fixed, i.e., like CIDR, not the number of bits that are free - * like OpenFlow encodes. - * - * @return a number between 0 (matches all IPs) and 32 (exact match) - */ - public int getNetworkSourceMaskLen() { - return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT), - 0); - } - - /** - * Get nw_proto - * - * @return - */ - public byte getNetworkProtocol() { - return this.networkProtocol; - } - - /** - * Set nw_proto - * - * @param networkProtocol - */ - public OFMatch setNetworkProtocol(byte networkProtocol) { - this.networkProtocol = networkProtocol; - return this; - } - - /** - * Get nw_src - * - * @return - */ - public int getNetworkSource() { - return this.networkSource; - } - - /** - * Set nw_src - * - * @param networkSource - */ - public OFMatch setNetworkSource(int networkSource) { - this.networkSource = networkSource; - return this; - } - - /** - * Get nw_tos OFMatch stores the ToS bits as top 6-bits, so right shift by 2 - * bits before returning the value - * - * @return : 6-bit DSCP value (0-63) - */ - public byte getNetworkTypeOfService() { - return (byte) ((this.networkTypeOfService >> 2) & 0x3f); - } - - /** - * Set nw_tos OFMatch stores the ToS bits as top 6-bits, so left shift by 2 - * bits before storing the value - * - * @param networkTypeOfService - * : 6-bit DSCP value (0-63) - */ - public OFMatch setNetworkTypeOfService(byte networkTypeOfService) { - this.networkTypeOfService = (byte) (networkTypeOfService << 2); - return this; - } - - /** - * Get tp_dst - * - * @return - */ - public short getTransportDestination() { - return this.transportDestination; - } - - /** - * Set tp_dst - * - * @param transportDestination - */ - public OFMatch setTransportDestination(short transportDestination) { - this.transportDestination = transportDestination; - return this; - } - - /** - * Get tp_src - * - * @return - */ - public short getTransportSource() { - return this.transportSource; - } - - /** - * Set tp_src - * - * @param transportSource - */ - public OFMatch setTransportSource(short transportSource) { - this.transportSource = transportSource; - return this; - } - - /** - * Get wildcards - * - * @return - */ - public int getWildcards() { - return this.wildcards; - } - - /** - * Get wildcards - * - * @return - */ - public Wildcards getWildcardObj() { - return Wildcards.of(wildcards); - } - - /** - * Set wildcards - * - * @param wildcards - */ - public OFMatch setWildcards(int wildcards) { - this.wildcards = wildcards; - return this; - } - - /** set the wildcard using the Wildcards convenience object */ - public OFMatch setWildcards(Wildcards wildcards) { - this.wildcards = wildcards.getInt(); - return this; - } - - /** - * Initializes this OFMatch structure with the corresponding data from the - * specified packet. Must specify the input port, to ensure that - * this.in_port is set correctly. Specify OFPort.NONE or OFPort.ANY if input - * port not applicable or available - * - * @param packetData - * The packet's data - * @param inputPort - * the port the packet arrived on - */ - public OFMatch loadFromPacket(byte[] packetData, short inputPort) { - short scratch; - int transportOffset = 34; - ByteBuffer packetDataBB = ByteBuffer.wrap(packetData); - int limit = packetDataBB.limit(); - - this.wildcards = 0; // all fields have explicit entries - - this.inputPort = inputPort; - - if (inputPort == OFPort.OFPP_ALL.getValue()) - this.wildcards |= OFPFW_IN_PORT; - - assert (limit >= 14); - // dl dst - this.dataLayerDestination = new byte[6]; - packetDataBB.get(this.dataLayerDestination); - // dl src - this.dataLayerSource = new byte[6]; - packetDataBB.get(this.dataLayerSource); - // dl type - this.dataLayerType = packetDataBB.getShort(); - - if (getDataLayerType() != (short) 0x8100) { // need cast to avoid signed - // bug - setDataLayerVirtualLan((short) 0xffff); - setDataLayerVirtualLanPriorityCodePoint((byte) 0); - } else { - // has vlan tag - scratch = packetDataBB.getShort(); - setDataLayerVirtualLan((short) (0xfff & scratch)); - setDataLayerVirtualLanPriorityCodePoint((byte) ((0xe000 & scratch) >> 13)); - this.dataLayerType = packetDataBB.getShort(); - } - - switch (getDataLayerType()) { - case 0x0800: - // ipv4 - // check packet length - scratch = packetDataBB.get(); - scratch = (short) (0xf & scratch); - transportOffset = (packetDataBB.position() - 1) - + (scratch * 4); - // nw tos (dscp) - scratch = packetDataBB.get(); - setNetworkTypeOfService((byte) ((0xfc & scratch) >> 2)); - // nw protocol - packetDataBB.position(packetDataBB.position() + 7); - this.networkProtocol = packetDataBB.get(); - // nw src - packetDataBB.position(packetDataBB.position() + 2); - this.networkSource = packetDataBB.getInt(); - // nw dst - this.networkDestination = packetDataBB.getInt(); - packetDataBB.position(transportOffset); - break; - case 0x0806: - // arp - int arpPos = packetDataBB.position(); - // opcode - scratch = packetDataBB.getShort(arpPos + 6); - setNetworkProtocol((byte) (0xff & scratch)); - - scratch = packetDataBB.getShort(arpPos + 2); - // if ipv4 and addr len is 4 - if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) { - // nw src - this.networkSource = packetDataBB.getInt(arpPos + 14); - // nw dst - this.networkDestination = packetDataBB.getInt(arpPos + 24); - } else { - setNetworkSource(0); - setNetworkDestination(0); - } - break; - default: - // Not ARP or IP. Wildcard NW_DST and NW_SRC - this.wildcards |= OFPFW_NW_DST_ALL | - OFPFW_NW_SRC_ALL | - OFPFW_NW_PROTO | - OFPFW_NW_TOS; - setNetworkTypeOfService((byte) 0); - setNetworkProtocol((byte) 0); - setNetworkSource(0); - setNetworkDestination(0); - break; - } - - switch (getNetworkProtocol()) { - case 0x01: - // icmp - // type - this.transportSource = U8.f(packetDataBB.get()); - // code - this.transportDestination = U8.f(packetDataBB.get()); - break; - case 0x06: - // tcp - // tcp src - this.transportSource = packetDataBB.getShort(); - // tcp dest - this.transportDestination = packetDataBB.getShort(); - break; - case 0x11: - // udp - // udp src - this.transportSource = packetDataBB.getShort(); - // udp dest - this.transportDestination = packetDataBB.getShort(); - break; - default: - // Unknown network proto. - this.wildcards |= OFPFW_TP_DST | OFPFW_TP_SRC; - setTransportDestination((short) 0); - setTransportSource((short) 0); - break; - } - return this; - } - - /** - * Read this message off the wire from the specified ByteBuffer - * - * @param data - */ - public void readFrom(ChannelBuffer data) { - this.wildcards = data.readInt(); - this.inputPort = data.readShort(); - this.dataLayerSource = new byte[6]; - data.readBytes(this.dataLayerSource); - this.dataLayerDestination = new byte[6]; - data.readBytes(this.dataLayerDestination); - this.dataLayerVirtualLan = data.readShort(); - this.dataLayerVirtualLanPriorityCodePoint = data.readByte(); - data.readByte(); // pad - this.dataLayerType = data.readShort(); - this.networkTypeOfService = data.readByte(); - this.networkProtocol = data.readByte(); - data.readByte(); // pad - data.readByte(); // pad - this.networkSource = data.readInt(); - this.networkDestination = data.readInt(); - this.transportSource = data.readShort(); - this.transportDestination = data.readShort(); - } - - /** - * Write this message's binary format to the specified ByteBuffer - * - * @param data - */ - public void writeTo(ChannelBuffer data) { - data.writeInt(wildcards); - data.writeShort(inputPort); - data.writeBytes(this.dataLayerSource); - data.writeBytes(this.dataLayerDestination); - data.writeShort(dataLayerVirtualLan); - data.writeByte(dataLayerVirtualLanPriorityCodePoint); - data.writeByte((byte) 0x0); // pad - data.writeShort(dataLayerType); - data.writeByte(networkTypeOfService); - data.writeByte(networkProtocol); - data.writeByte((byte) 0x0); // pad - data.writeByte((byte) 0x0); // pad - data.writeInt(networkSource); - data.writeInt(networkDestination); - data.writeShort(transportSource); - data.writeShort(transportDestination); - } - - @Override - public int hashCode() { - final int prime = 131; - int result = 1; - result = prime * result + Arrays.hashCode(dataLayerDestination); - result = prime * result + Arrays.hashCode(dataLayerSource); - result = prime * result + dataLayerType; - result = prime * result + dataLayerVirtualLan; - result = prime * result + dataLayerVirtualLanPriorityCodePoint; - result = prime * result + inputPort; - result = prime * result + networkDestination; - result = prime * result + networkProtocol; - result = prime * result + networkSource; - result = prime * result + networkTypeOfService; - result = prime * result + transportDestination; - result = prime * result + transportSource; - result = prime * result + wildcards; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFMatch)) { - return false; - } - OFMatch other = (OFMatch) obj; - if (!Arrays.equals(dataLayerDestination, other.dataLayerDestination)) { - return false; - } - if (!Arrays.equals(dataLayerSource, other.dataLayerSource)) { - return false; - } - if (dataLayerType != other.dataLayerType) { - return false; - } - if (dataLayerVirtualLan != other.dataLayerVirtualLan) { - return false; - } - if (dataLayerVirtualLanPriorityCodePoint != other.dataLayerVirtualLanPriorityCodePoint) { - return false; - } - if (inputPort != other.inputPort) { - return false; - } - if (networkDestination != other.networkDestination) { - return false; - } - if (networkProtocol != other.networkProtocol) { - return false; - } - if (networkSource != other.networkSource) { - return false; - } - if (networkTypeOfService != other.networkTypeOfService) { - return false; - } - if (transportDestination != other.transportDestination) { - return false; - } - if (transportSource != other.transportSource) { - return false; - } - if ((wildcards & OFMatch.OFPFW_ALL) != (other.wildcards & OFPFW_ALL)) { // only - // consider - // allocated - // part - // of - // wildcards - return false; - } - return true; - } - - /** - * Implement clonable interface - */ - @Override - public OFMatch clone() { - try { - OFMatch ret = (OFMatch) super.clone(); - ret.dataLayerDestination = this.dataLayerDestination.clone(); - ret.dataLayerSource = this.dataLayerSource.clone(); - return ret; - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - - /** - * matching two OFMatch - * @param toCompare - * @return - */ - public boolean match(OFMatch toCompare) { - if ((wildcards & OFPFW_IN_PORT) == 0 && - this.inputPort != toCompare.getInputPort()) - return false; - if ((wildcards & OFPFW_DL_DST) == 0 && - !Arrays.equals(this.dataLayerDestination, toCompare.getDataLayerDestination())) - return false; - if ((wildcards & OFPFW_DL_SRC) == 0 && - !Arrays.equals(this.dataLayerSource, toCompare.getDataLayerSource())) - return false; - if ((wildcards & OFPFW_DL_TYPE) == 0 - && this.dataLayerType != toCompare.getDataLayerType()) - return false; - if ((wildcards & OFPFW_DL_VLAN) == 0 && - this.dataLayerVirtualLan != toCompare.getDataLayerVirtualLan()) - return false; - if ((wildcards & OFPFW_DL_VLAN_PCP) == 0 && - this.dataLayerVirtualLanPriorityCodePoint != toCompare.getDataLayerVirtualLanPriorityCodePoint()) - return false; - if ((wildcards & OFPFW_NW_PROTO) == 0 && - this.networkProtocol != toCompare.getNetworkProtocol()) - return false; - if ((wildcards & OFPFW_NW_TOS) == 0 && - this.networkTypeOfService != toCompare.getNetworkTypeOfService()) - return false; - //compare network layer src/dst - - int dstmasklen = getNetworkDestinationMaskLen(); - int srcmasklen = getNetworkSourceMaskLen(); - if (dstmasklen >= 32 && networkDestination != toCompare.getNetworkDestination()) - return false; - if (srcmasklen >= 32 && networkSource != toCompare.getNetworkSource()) - return false; - int dstmask = ~((1 << (32 - dstmasklen)) - 1); - int srcmask = ~((1 << (32 - srcmasklen)) - 1); - if (dstmasklen < 32 && - (networkDestination & dstmask) != (toCompare.getNetworkDestination() & dstmask)) - return false; - if (srcmasklen < 32 && - (networkSource & srcmask) != (toCompare.getNetworkSource() & srcmask)) - return false; - //layer 4 - if ((wildcards & OFPFW_TP_DST) == 0 && - this.transportDestination != toCompare.getTransportDestination()) - return false; - if ((wildcards & OFPFW_TP_SRC) == 0 && - this.transportSource != toCompare.getTransportSource()) - return false; - return true; - } - - /** - * Output a dpctl-styled string, i.e., only list the elements that are not - * wildcarded A match-everything OFMatch outputs "OFMatch[]" - * - * @return - * "OFMatch[dl_src:00:20:01:11:22:33,nw_src:192.168.0.0/24,tp_dst:80]" - */ - @Override - public String toString() { - String str = ""; - - // l1 - if ((wildcards & OFPFW_IN_PORT) == 0) - str += "," + STR_IN_PORT + "=" - + U16.f(this.inputPort); - - // l2 - if ((wildcards & OFPFW_DL_DST) == 0) - str += "," - + STR_DL_DST - + "=" - + HexString.toHexString(this.dataLayerDestination); - if ((wildcards & OFPFW_DL_SRC) == 0) - str += "," - + STR_DL_SRC - + "=" - + HexString.toHexString(this.dataLayerSource); - if ((wildcards & OFPFW_DL_TYPE) == 0) - str += "," - + STR_DL_TYPE - + "=0x" - + Integer.toHexString(U16.f(this.dataLayerType)); - if ((wildcards & OFPFW_DL_VLAN) == 0) - str += "," - + STR_DL_VLAN - + "=0x" - + Integer.toHexString(U16.f(this.dataLayerVirtualLan)); - if ((wildcards & OFPFW_DL_VLAN_PCP) == 0) - str += "," - + STR_DL_VLAN_PCP - + "=" - + Integer.toHexString(U8.f(this.dataLayerVirtualLanPriorityCodePoint)); - - // l3 - if (getNetworkDestinationMaskLen() > 0) - str += "," - + STR_NW_DST - + "=" - + cidrToString(networkDestination, - getNetworkDestinationMaskLen()); - if (getNetworkSourceMaskLen() > 0) - str += "," - + STR_NW_SRC - + "=" - + cidrToString(networkSource, - getNetworkSourceMaskLen()); - if ((wildcards & OFPFW_NW_PROTO) == 0) - str += "," + STR_NW_PROTO - + "=" - + this.networkProtocol; - if ((wildcards & OFPFW_NW_TOS) == 0) - str += "," - + STR_NW_TOS - + "=" - + this.getNetworkTypeOfService(); - - // l4 - if ((wildcards & OFPFW_TP_DST) == 0) - str += "," - + STR_TP_DST - + "=" - + this.transportDestination; - if ((wildcards & OFPFW_TP_SRC) == 0) - str += "," + STR_TP_SRC + "=" - + this.transportSource; - if ((str.length() > 0) && (str.charAt(0) == ',')) - str = str.substring(1); // trim - // the - // leading - // "," - // done - return "OFMatch[" + str + "]"; - } - - /** - * Return a string including all match fields, regardless whether they - * are wildcarded or not. - */ - public String toStringUnmasked() { - String str = ""; - - // l1 - str += STR_IN_PORT + "=" + U16.f(this.inputPort); - - // l2 - str += "," + STR_DL_DST + "=" - + HexString.toHexString(this.dataLayerDestination); - str += "," + STR_DL_SRC + "=" - + HexString.toHexString(this.dataLayerSource); - str += "," + STR_DL_TYPE + "=0x" - + Integer.toHexString(U16.f(this.dataLayerType)); - str += "," + STR_DL_VLAN + "=0x" - + Integer.toHexString(U16.f(this.dataLayerVirtualLan)); - str += "," + STR_DL_VLAN_PCP + "=" - + Integer.toHexString(U8.f(this.dataLayerVirtualLanPriorityCodePoint)); - - // l3 - str += "," + STR_NW_DST + "=" - + cidrToString(networkDestination, - getNetworkDestinationMaskLen()); - str += "," + STR_NW_SRC + "=" - + cidrToString(networkSource, - getNetworkSourceMaskLen()); - str += "," + STR_NW_PROTO + "=" + this.networkProtocol; - str += "," + STR_NW_TOS + "=" + this.getNetworkTypeOfService(); - - // l4 - str += "," + STR_TP_DST + "=" + this.transportDestination; - str += "," + STR_TP_SRC + "=" + this.transportSource; - - // wildcards - str += ", wildcards=" + debugWildCards(wildcards); - return "OFMatch[" + str + "]"; - } - - /** - * debug a set of wildcards - */ - public static String debugWildCards(int wildcards) { - String str = ""; - - // l1 - if ((wildcards & OFPFW_IN_PORT) != 0) str += "|" + STR_IN_PORT; - - // l2 - if ((wildcards & OFPFW_DL_DST) != 0) str += "|" + STR_DL_DST; - if ((wildcards & OFPFW_DL_SRC) != 0) str += "|" + STR_DL_SRC; - if ((wildcards & OFPFW_DL_TYPE) != 0) str += "|" + STR_DL_TYPE; - if ((wildcards & OFPFW_DL_VLAN) != 0) str += "|" + STR_DL_VLAN; - if ((wildcards & OFPFW_DL_VLAN_PCP) != 0) - str += "|" - + STR_DL_VLAN_PCP; - - int nwDstMask = Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT), - 0); - int nwSrcMask = Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT), - 0); - - // l3 - if (nwDstMask < 32) - str += "|" + STR_NW_DST + "(/" + nwDstMask + ")"; - - if (nwSrcMask < 32) - str += "|" + STR_NW_SRC + "(/" + nwSrcMask + ")"; - - if ((wildcards & OFPFW_NW_PROTO) != 0) str += "|" + STR_NW_PROTO; - if ((wildcards & OFPFW_NW_TOS) != 0) str += "|" + STR_NW_TOS; - - // l4 - if ((wildcards & OFPFW_TP_DST) != 0) str += "|" + STR_TP_DST; - if ((wildcards & OFPFW_TP_SRC) != 0) str += "|" + STR_TP_SRC; - if ((str.length() > 0) && (str.charAt(0) == '|')) - str = str.substring(1); // trim - // the - // leading - // "," - // done - return str; - } - - private String cidrToString(int ip, int prefix) { - String str; - if (prefix >= 32) { - str = ipToString(ip); - } else { - // use the negation of mask to fake endian magic - int mask = ~((1 << (32 - prefix)) - 1); - str = ipToString(ip & mask) + "/" + prefix; - } - - return str; - } - - /** - * Set this OFMatch's parameters based on a comma-separated key=value pair - * dpctl-style string, e.g., from the output of OFMatch.toString() <br> - * <p> - * Supported keys/values include <br> - * <p> - * <TABLE border=1> - * <TR> - * <TD>KEY(s) - * <TD>VALUE - * </TR> - * <TR> - * <TD>"in_port","input_port" - * <TD>integer - * </TR> - * <TR> - * <TD>"dl_src","eth_src", "dl_dst","eth_dst" - * <TD>hex-string - * </TR> - * <TR> - * <TD>"dl_type", "dl_vlan", "dl_vlan_pcp" - * <TD>integer - * </TR> - * <TR> - * <TD>"nw_src", "nw_dst", "ip_src", "ip_dst" - * <TD>CIDR-style netmask - * </TR> - * <TR> - * <TD>"tp_src","tp_dst" - * <TD>integer (max 64k) - * </TR> - * </TABLE> - * <p> - * The CIDR-style netmasks assume 32 netmask if none given, so: - * "128.8.128.118/32" is the same as "128.8.128.118" - * - * @param match - * a key=value comma separated string, e.g. - * "in_port=5,ip_dst=192.168.0.0/16,tp_src=80" - * @throws IllegalArgumentException - * on unexpected key or value - */ - - public void fromString(String match) throws IllegalArgumentException { - if (match.equals("") || match.equalsIgnoreCase("any") - || match.equalsIgnoreCase("all") || match.equals("[]")) - match = "OFMatch[]"; - String[] tokens = match.split("[\\[,\\]]"); - String[] values; - int initArg = 0; - if (tokens[0].equals("OFMatch")) initArg = 1; - this.wildcards = OFPFW_ALL; - int i; - for (i = initArg; i < tokens.length; i++) { - values = tokens[i].split("="); - if (values.length != 2) - throw new IllegalArgumentException( - "Token " - + tokens[i] - + " does not have form 'key=value' parsing " - + match); - values[0] = values[0].toLowerCase(); // try to make this case insens - if (values[0].equals(STR_IN_PORT) - || values[0].equals("input_port")) { - this.inputPort = U16.t(Integer.valueOf(values[1])); - this.wildcards &= ~OFPFW_IN_PORT; - } else if (values[0].equals(STR_DL_DST) - || values[0].equals("eth_dst")) { - this.dataLayerDestination = HexString.fromHexString(values[1]); - this.wildcards &= ~OFPFW_DL_DST; - } else if (values[0].equals(STR_DL_SRC) - || values[0].equals("eth_src")) { - this.dataLayerSource = HexString.fromHexString(values[1]); - this.wildcards &= ~OFPFW_DL_SRC; - } else if (values[0].equals(STR_DL_TYPE) - || values[0].equals("eth_type")) { - if (values[1].startsWith("0x")) - this.dataLayerType = U16.t(Integer.valueOf(values[1].replaceFirst("0x", - ""), - 16)); - else - this.dataLayerType = U16.t(Integer.valueOf(values[1])); - this.wildcards &= ~OFPFW_DL_TYPE; - } else if (values[0].equals(STR_DL_VLAN)) { - if (values[1].startsWith("0x")) - this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1].replaceFirst("0x", - ""), - 16)); - else - this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1])); - this.wildcards &= ~OFPFW_DL_VLAN; - } else if (values[0].equals(STR_DL_VLAN_PCP)) { - this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short.valueOf(values[1])); - this.wildcards &= ~OFPFW_DL_VLAN_PCP; - } else if (values[0].equals(STR_NW_DST) - || values[0].equals("ip_dst")) { - setFromCIDR(values[1], STR_NW_DST); - } else if (values[0].equals(STR_NW_SRC) - || values[0].equals("ip_src")) { - setFromCIDR(values[1], STR_NW_SRC); - } else if (values[0].equals(STR_NW_PROTO)) { - if (values[1].startsWith("0x")) - this.networkProtocol = U8.t(Short.valueOf(values[1].replaceFirst("0x",""),16)); - else - this.networkProtocol = U8.t(Short.valueOf(values[1])); - this.wildcards &= ~OFPFW_NW_PROTO; - } else if (values[0].equals(STR_NW_TOS)) { - this.setNetworkTypeOfService(U8.t(Short.valueOf(values[1]))); - this.wildcards &= ~OFPFW_NW_TOS; - } else if (values[0].equals(STR_TP_DST)) { - this.transportDestination = U16.t(Integer.valueOf(values[1])); - this.wildcards &= ~OFPFW_TP_DST; - } else if (values[0].equals(STR_TP_SRC)) { - this.transportSource = U16.t(Integer.valueOf(values[1])); - this.wildcards &= ~OFPFW_TP_SRC; - } else { - throw new IllegalArgumentException("unknown token " - + tokens[i] + " parsing " - + match); - } - } - } - - /** - * Set the networkSource or networkDestionation address and their wildcards - * from the CIDR string - * - * @param cidr - * "192.168.0.0/16" or "172.16.1.5" - * @param which - * one of STR_NW_DST or STR_NW_SRC - * @throws IllegalArgumentException - */ - private - void - setFromCIDR(String cidr, String which) - throws IllegalArgumentException { - String values[] = cidr.split("/"); - String[] ip_str = values[0].split("\\."); - int ip = 0; - ip += Integer.valueOf(ip_str[0]) << 24; - ip += Integer.valueOf(ip_str[1]) << 16; - ip += Integer.valueOf(ip_str[2]) << 8; - ip += Integer.valueOf(ip_str[3]); - int prefix = 32; // all bits are fixed, by default - - if (values.length >= 2) prefix = Integer.valueOf(values[1]); - int mask = 32 - prefix; - if (which.equals(STR_NW_DST)) { - this.networkDestination = ip; - this.wildcards = (wildcards & ~OFPFW_NW_DST_MASK) - | (mask << OFPFW_NW_DST_SHIFT); - } else if (which.equals(STR_NW_SRC)) { - this.networkSource = ip; - this.wildcards = (wildcards & ~OFPFW_NW_SRC_MASK) - | (mask << OFPFW_NW_SRC_SHIFT); - } - } - - protected static String ipToString(int ip) { - return Integer.toString(U8.f((byte) ((ip & 0xff000000) >> 24))) - + "." + Integer.toString((ip & 0x00ff0000) >> 16) + "." - + Integer.toString((ip & 0x0000ff00) >> 8) + "." - + Integer.toString(ip & 0x000000ff); - } -} diff --git a/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java b/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java deleted file mode 100644 index 97e14a5592b90062153acd0d77b28168250edb38..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java +++ /dev/null @@ -1,101 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.beans.SimpleBeanInfo; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.LinkedList; -import java.util.List; - -/** - * Extra info for how to treat OFMatch as a JavaBean - * - * For some (inane!) reason, using chained setters in OFMatch breaks a lot of the JavaBean defaults. - * - * We don't really use OFMatch as a java bean, but there are a lot of nice XML utils that work for - * free if OFMatch follows the java bean paradigm. - * - * @author Rob Sherwood (rob.sherwood@stanford.edu) - * - */ - -public class OFMatchBeanInfo extends SimpleBeanInfo { - - @Override - public PropertyDescriptor[] getPropertyDescriptors() { - List<PropertyDescriptor> descs = new LinkedList<PropertyDescriptor>(); - Field[] fields = OFMatch.class.getDeclaredFields(); - String name; - for (int i=0; i< fields.length; i++) { - int mod = fields[i].getModifiers(); - if(Modifier.isFinal(mod) || // don't expose static or final fields - Modifier.isStatic(mod)) - continue; - - name = fields[i].getName(); - Class<?> type = fields[i].getType(); - - try { - descs.add(new PropertyDescriptor(name, - name2getter(OFMatch.class, name), - name2setter(OFMatch.class, name, type))); - } catch (IntrospectionException e) { - throw new RuntimeException(e); - } - } - - return descs.toArray(new PropertyDescriptor[0]); - } - - - private Method name2setter(Class<OFMatch> c, String name, Class<?> type) { - String mName = "set" + toLeadingCaps(name); - Method m = null; - try { - m = c.getMethod(mName, new Class[]{ type}); - } catch (SecurityException e) { - throw new RuntimeException(e); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - return m; - } - - private Method name2getter(Class<OFMatch> c, String name) { - String mName= "get" + toLeadingCaps(name); - Method m = null; - try { - m = c.getMethod(mName, new Class[]{}); - } catch (SecurityException e) { - throw new RuntimeException(e); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - return m; - } - - private String toLeadingCaps(String s) { - char[] array = s.toCharArray(); - array[0] = Character.toUpperCase(array[0]); - return String.valueOf(array, 0, array.length); - } -} diff --git a/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java b/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java deleted file mode 100644 index 04ecf5e5edea269c912af7b0f5d8b65b17ebaa80..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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 org.openflow.protocol; - -import org.openflow.util.HexString; - -public class OFMatchWithSwDpid { - protected OFMatch ofMatch; - protected long switchDataPathId; - - public OFMatchWithSwDpid() { - this.ofMatch = new OFMatch(); - this.switchDataPathId = 0; - } - - public OFMatchWithSwDpid(OFMatch ofm, long swDpid) { - this.ofMatch = ofm.clone(); - this.switchDataPathId = swDpid; - } - public OFMatch getOfMatch() { - return ofMatch; - } - - public void setOfMatch(OFMatch ofMatch) { - this.ofMatch = ofMatch.clone(); - } - - public long getSwitchDataPathId() { - return this.switchDataPathId; - } - - public OFMatchWithSwDpid setSwitchDataPathId(long dpid) { - this.switchDataPathId = dpid; - return this; - } - - @Override - public String toString() { - return "OFMatchWithSwDpid [" + HexString.toHexString(switchDataPathId) - + " " + ofMatch + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((ofMatch == null) ? 0 : ofMatch.hashCode()); - result = prime * result - + (int) (switchDataPathId ^ (switchDataPathId >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFMatchWithSwDpid)) { - return false; - } - OFMatchWithSwDpid other = (OFMatchWithSwDpid) obj; - if (ofMatch == null) { - if (other.ofMatch != null) { - return false; - } - } else if (!ofMatch.equals(other.ofMatch)) { - return false; - } - if (switchDataPathId != other.switchDataPathId) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFMessage.java b/src/main/java/org/openflow/protocol/OFMessage.java deleted file mode 100644 index 38f4e477317e79682416b2145985bd4fa3948f5f..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFMessage.java +++ /dev/null @@ -1,336 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.concurrent.ConcurrentHashMap; - -import net.floodlightcontroller.core.FloodlightContext; -import net.floodlightcontroller.core.IFloodlightProviderService; -import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.packet.Ethernet; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.HexString; -import org.openflow.util.U16; -import org.openflow.util.U32; -import org.openflow.util.U8; - -/** - * The base class for all OpenFlow protocol messages. This class contains the - * equivalent of the ofp_header which is present in all OpenFlow messages. - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 3, 2010 - * @author Rob Sherwood (rob.sherwood@stanford.edu) - Feb 3, 2010 - */ -public class OFMessage { - public static final int MAXIMUM_LENGTH = (1 << 16) - 1; - public static byte OFP_VERSION = 0x01; - public static int MINIMUM_LENGTH = 8; - - protected byte version; - protected OFType type; - protected short length; - protected int xid; - - private ConcurrentHashMap<String, Object> storage; - - public OFMessage() { - storage = null; - this.version = OFP_VERSION; - } - - protected synchronized ConcurrentHashMap<String, Object> getMessageStore() { - if (storage == null) { - storage = new ConcurrentHashMap<String, Object>();; - } - return storage; - } - - /** - * Get the length of this message - * - * @return - */ - public short getLength() { - return length; - } - - /** - * Get the length of this message, unsigned - * - * @return - */ - public int getLengthU() { - return U16.f(length); - } - - /** - * Set the length of this message - * - * @param length - */ - public OFMessage setLength(short length) { - this.length = length; - return this; - } - - /** - * Set the length of this message, unsigned - * - * @param length - */ - public OFMessage setLengthU(int length) { - this.length = U16.t(length); - return this; - } - - /** - * Get the type of this message - * - * @return - */ - public OFType getType() { - return type; - } - - /** - * Set the type of this message - * - * @param type - */ - public void setType(OFType type) { - this.type = type; - } - - /** - * Get the OpenFlow version of this message - * - * @return - */ - public byte getVersion() { - return version; - } - - /** - * Set the OpenFlow version of this message - * - * @param version - */ - public void setVersion(byte version) { - this.version = version; - } - - /** - * Get the transaction id of this message - * - * @return - */ - public int getXid() { - return xid; - } - - /** - * Set the transaction id of this message - * - * @param xid - */ - public void setXid(int xid) { - this.xid = xid; - } - - /** - * Read this message off the wire from the specified ByteBuffer - * @param data - */ - public void readFrom(ChannelBuffer data) { - this.version = data.readByte(); - this.type = OFType.valueOf(data.readByte()); - this.length = data.readShort(); - this.xid = data.readInt(); - } - - /** - * Write this message's binary format to the specified ByteBuffer - * @param data - */ - public void writeTo(ChannelBuffer data) { - data.writeByte(version); - data.writeByte(type.getTypeValue()); - data.writeShort(length); - data.writeInt(xid); - } - - /** - * Returns a summary of the message - * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid" - */ - @Override - public String toString() { - return "ofmsg" + - ":v=" + U8.f(this.getVersion()) + - ";t=" + this.getType() + - ";l=" + this.getLengthU() + - ";x=" + U32.f(this.getXid()); - } - - @Override - public int hashCode() { - final int prime = 97; - int result = 1; - result = prime * result + length; - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + version; - result = prime * result + xid; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFMessage)) { - return false; - } - OFMessage other = (OFMessage) obj; - if (length != other.length) { - return false; - } - if (type == null) { - if (other.type != null) { - return false; - } - } else if (!type.equals(other.type)) { - return false; - } - if (version != other.version) { - return false; - } - if (xid != other.xid) { - return false; - } - return true; - } - - public static String getDataAsString(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { - - Ethernet eth; - StringBuffer sb = new StringBuffer(""); - - DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS"); - Date date = new Date(); - - sb.append(dateFormat.format(date)); - sb.append(" "); - - switch (msg.getType()) { - case PACKET_IN: - OFPacketIn pktIn = (OFPacketIn) msg; - sb.append("packet_in [ "); - sb.append(sw.getStringId()); - sb.append(" -> Controller"); - sb.append(" ]"); - - sb.append("\ntotal length: "); - sb.append(pktIn.getTotalLength()); - sb.append("\nin_port: "); - sb.append(pktIn.getInPort()); - sb.append("\ndata_length: "); - sb.append(pktIn.getTotalLength() - OFPacketIn.MINIMUM_LENGTH); - sb.append("\nbuffer: "); - sb.append(pktIn.getBufferId()); - - // If the conext is not set by floodlight, then ignore. - if (cntx != null) { - // packet type icmp, arp, etc. - eth = IFloodlightProviderService.bcStore.get(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - if (eth != null) - sb.append(eth.toString()); - } - break; - - case PACKET_OUT: - OFPacketOut pktOut = (OFPacketOut) msg; - sb.append("packet_out [ "); - sb.append("Controller -> "); - sb.append(HexString.toHexString(sw.getId())); - sb.append(" ]"); - - sb.append("\nin_port: "); - sb.append(pktOut.getInPort()); - sb.append("\nactions_len: "); - sb.append(pktOut.getActionsLength()); - if (pktOut.getActions() != null) { - sb.append("\nactions: "); - sb.append(pktOut.getActions().toString()); - } - break; - - case FLOW_MOD: - OFFlowMod fm = (OFFlowMod) msg; - sb.append("flow_mod [ "); - sb.append("Controller -> "); - sb.append(HexString.toHexString(sw.getId())); - sb.append(" ]"); - - // If the conext is not set by floodlight, then ignore. - if (cntx != null) { - eth = IFloodlightProviderService.bcStore.get(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD); - if (eth != null) - sb.append(eth.toString()); - } - - sb.append("\nADD: cookie: "); - sb.append(fm.getCookie()); - sb.append(" idle: "); - sb.append(fm.getIdleTimeout()); - sb.append(" hard: "); - sb.append(fm.getHardTimeout()); - sb.append(" pri: "); - sb.append(fm.getPriority()); - sb.append(" buf: "); - sb.append(fm.getBufferId()); - sb.append(" flg: "); - sb.append(fm.getFlags()); - if (fm.getActions() != null) { - sb.append("\nactions: "); - sb.append(fm.getActions().toString()); - } - break; - - default: - sb.append("[Unknown Packet]"); - } - - sb.append("\n\n"); - return sb.toString(); - - } - - public static byte[] getData(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { - return OFMessage.getDataAsString(sw, msg, cntx).getBytes(); - } -} diff --git a/src/main/java/org/openflow/protocol/OFMessageContextStore.java b/src/main/java/org/openflow/protocol/OFMessageContextStore.java deleted file mode 100644 index b60aa1cd4b981ef94335bf1eb67447894de2cf15..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFMessageContextStore.java +++ /dev/null @@ -1,39 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.protocol.OFMessage; - -public class OFMessageContextStore<V> { - protected OFMessage msg; - String namespace; - - public OFMessageContextStore(OFMessage msg, String namespace) { - this.msg = msg; - this.namespace = namespace; - } - - @SuppressWarnings("unchecked") - public V get(String key) { - return (V)msg.getMessageStore().get(namespace + "|" + key); - } - - public void put(String key, V value) { - msg.getMessageStore().put(namespace + "|" + key, value); - } -} diff --git a/src/main/java/org/openflow/protocol/OFPacketIn.java b/src/main/java/org/openflow/protocol/OFPacketIn.java deleted file mode 100644 index c37c9184cc0bd710989a0b8197aab5146b6d8ad2..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPacketIn.java +++ /dev/null @@ -1,211 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; -import org.openflow.util.U32; -import org.openflow.util.U8; - -/** - * Represents an ofp_packet_in - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 8, 2010 - */ -public class OFPacketIn extends OFMessage { - public static short MINIMUM_LENGTH = 18; - - public enum OFPacketInReason { - NO_MATCH, ACTION - } - - protected int bufferId; - protected short totalLength; - protected short inPort; - protected OFPacketInReason reason; - protected byte[] packetData; - - public OFPacketIn() { - super(); - this.type = OFType.PACKET_IN; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * Get buffer_id - * @return - */ - public int getBufferId() { - return this.bufferId; - } - - /** - * Set buffer_id - * @param bufferId - */ - public OFPacketIn setBufferId(int bufferId) { - this.bufferId = bufferId; - return this; - } - - /** - * Returns the packet data - * @return - */ - public byte[] getPacketData() { - return this.packetData; - } - - /** - * Sets the packet data, and updates the length of this message - * @param packetData - */ - public OFPacketIn setPacketData(byte[] packetData) { - this.packetData = packetData; - this.length = U16.t(OFPacketIn.MINIMUM_LENGTH + packetData.length); - return this; - } - - /** - * Get in_port - * @return - */ - public short getInPort() { - return this.inPort; - } - - /** - * Set in_port - * @param inPort - */ - public OFPacketIn setInPort(short inPort) { - this.inPort = inPort; - return this; - } - - /** - * Get reason - * @return - */ - public OFPacketInReason getReason() { - return this.reason; - } - - /** - * Set reason - * @param reason - */ - public OFPacketIn setReason(OFPacketInReason reason) { - this.reason = reason; - return this; - } - - /** - * Get total_len - * @return - */ - public short getTotalLength() { - return this.totalLength; - } - - /** - * Set total_len - * @param totalLength - */ - public OFPacketIn setTotalLength(short totalLength) { - this.totalLength = totalLength; - return this; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.bufferId = data.readInt(); - this.totalLength = data.readShort(); - this.inPort = data.readShort(); - this.reason = OFPacketInReason.values()[U8.f(data.readByte())]; - data.readByte(); // pad - this.packetData = new byte[getLengthU() - MINIMUM_LENGTH]; - data.readBytes(this.packetData); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeInt(bufferId); - data.writeShort(totalLength); - data.writeShort(inPort); - data.writeByte((byte) reason.ordinal()); - data.writeByte((byte) 0x0); // pad - data.writeBytes(this.packetData); - } - - @Override - public int hashCode() { - final int prime = 283; - int result = super.hashCode(); - result = prime * result + bufferId; - result = prime * result + inPort; - result = prime * result + Arrays.hashCode(packetData); - result = prime * result + ((reason == null) ? 0 : reason.hashCode()); - result = prime * result + totalLength; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFPacketIn)) { - return false; - } - OFPacketIn other = (OFPacketIn) obj; - if (bufferId != other.bufferId) { - return false; - } - if (inPort != other.inPort) { - return false; - } - if (!Arrays.equals(packetData, other.packetData)) { - return false; - } - if (reason == null) { - if (other.reason != null) { - return false; - } - } else if (!reason.equals(other.reason)) { - return false; - } - if (totalLength != other.totalLength) { - return false; - } - return true; - } - - public String toString() { - String myStr = super.toString(); - return "packetIn" + - ":bufferId=" + U32.f(this.bufferId) + myStr; - } -} diff --git a/src/main/java/org/openflow/protocol/OFPacketOut.java b/src/main/java/org/openflow/protocol/OFPacketOut.java deleted file mode 100644 index ef4aa61f1b0e86a245bc6dd5ba9aa55c0ba2557d..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPacketOut.java +++ /dev/null @@ -1,260 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.Arrays; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.factory.OFActionFactory; -import org.openflow.protocol.factory.OFActionFactoryAware; -import org.openflow.util.HexString; -import org.openflow.util.U16; - -/** - * Represents an ofp_packet_out message - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 12, 2010 - */ -public class OFPacketOut extends OFMessage implements OFActionFactoryAware { - public static int MINIMUM_LENGTH = 16; - public static int BUFFER_ID_NONE = 0xffffffff; - - protected OFActionFactory actionFactory; - protected int bufferId; - protected short inPort; - protected short actionsLength; - protected List<OFAction> actions; - protected byte[] packetData; - - public OFPacketOut() { - super(); - this.type = OFType.PACKET_OUT; - this.length = U16.t(MINIMUM_LENGTH); - this.bufferId = BUFFER_ID_NONE; - } - - /** - * Get buffer_id - * @return - */ - public int getBufferId() { - return this.bufferId; - } - - /** - * Set buffer_id - * @param bufferId - */ - public OFPacketOut setBufferId(int bufferId) { - if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) { - throw new IllegalArgumentException( - "PacketOut should not have both bufferId and packetData set"); - } - this.bufferId = bufferId; - return this; - } - - /** - * Returns the packet data - * @return - */ - public byte[] getPacketData() { - return this.packetData; - } - - /** - * Sets the packet data - * @param packetData - */ - public OFPacketOut setPacketData(byte[] packetData) { - if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) { - throw new IllegalArgumentException( - "PacketOut should not have both bufferId and packetData set"); - } - this.packetData = packetData; - return this; - } - - /** - * Get in_port - * @return - */ - public short getInPort() { - return this.inPort; - } - - /** - * Set in_port - * @param inPort - */ - public OFPacketOut setInPort(short inPort) { - this.inPort = inPort; - return this; - } - - /** - * Set in_port. Convenience method using OFPort enum. - * @param inPort - */ - public OFPacketOut setInPort(OFPort inPort) { - this.inPort = inPort.getValue(); - return this; - } - - /** - * Get actions_len - * @return - */ - public short getActionsLength() { - return this.actionsLength; - } - - /** - * Get actions_len, unsigned - * @return - */ - public int getActionsLengthU() { - return U16.f(this.actionsLength); - } - - /** - * Set actions_len - * @param actionsLength - */ - public OFPacketOut setActionsLength(short actionsLength) { - this.actionsLength = actionsLength; - return this; - } - - /** - * Returns the actions contained in this message - * @return a list of ordered OFAction objects - */ - public List<OFAction> getActions() { - return this.actions; - } - - /** - * Sets the list of actions on this message - * @param actions a list of ordered OFAction objects - */ - public OFPacketOut setActions(List<OFAction> actions) { - this.actions = actions; - return this; - } - - @Override - public void setActionFactory(OFActionFactory actionFactory) { - this.actionFactory = actionFactory; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.bufferId = data.readInt(); - this.inPort = data.readShort(); - this.actionsLength = data.readShort(); - if ( this.actionFactory == null) - throw new RuntimeException("ActionFactory not set"); - this.actions = this.actionFactory.parseActions(data, getActionsLengthU()); - this.packetData = new byte[getLengthU() - MINIMUM_LENGTH - getActionsLengthU()]; - data.readBytes(this.packetData); - validate(); - } - - @Override - public void writeTo(ChannelBuffer data) { - validate(); - super.writeTo(data); - data.writeInt(bufferId); - data.writeShort(inPort); - data.writeShort(actionsLength); - for (OFAction action : actions) { - action.writeTo(data); - } - if (this.packetData != null) - data.writeBytes(this.packetData); - } - - /** validate the invariants of this OFMessage hold */ - public void validate() { - if (!((bufferId != BUFFER_ID_NONE) ^ (packetData != null && packetData.length > 0))) { - throw new IllegalStateException( - "OFPacketOut must have exactly one of (bufferId, packetData) set (not one, not both)"); - } - } - - @Override - public int hashCode() { - final int prime = 293; - int result = super.hashCode(); - result = prime * result + ((actions == null) ? 0 : actions.hashCode()); - result = prime * result + actionsLength; - result = prime * result + bufferId; - result = prime * result + inPort; - result = prime * result + Arrays.hashCode(packetData); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFPacketOut)) { - return false; - } - OFPacketOut other = (OFPacketOut) obj; - if (actions == null) { - if (other.actions != null) { - return false; - } - } else if (!actions.equals(other.actions)) { - return false; - } - if (actionsLength != other.actionsLength) { - return false; - } - if (bufferId != other.bufferId) { - return false; - } - if (inPort != other.inPort) { - return false; - } - if (!Arrays.equals(packetData, other.packetData)) { - return false; - } - return true; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "OFPacketOut [actionFactory=" + actionFactory + ", actions=" - + actions + ", actionsLength=" + actionsLength + ", bufferId=0x" - + Integer.toHexString(bufferId) + ", inPort=" + inPort + ", packetData=" - + HexString.toHexString(packetData) + "]"; - } -} diff --git a/src/main/java/org/openflow/protocol/OFPacketQueue.java b/src/main/java/org/openflow/protocol/OFPacketQueue.java deleted file mode 100644 index e8de1af56b950465c23cc140ad4991e0922aa34f..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPacketQueue.java +++ /dev/null @@ -1,142 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.protocol; - -import java.util.ArrayList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents ofp_packet_queue - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFPacketQueue { - public static int MINIMUM_LENGTH = 8; - - protected int queueId; - protected short length; - protected List<OFQueueProp> properties = new ArrayList<OFQueueProp>(); - - public OFPacketQueue() { - this.queueId = -1; - this.length = U16.t(MINIMUM_LENGTH); - } - - public OFPacketQueue(int queueId) { - this.queueId = queueId; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * @return the queueId - */ - public long getQueueId() { - return queueId; - } - - /** - * @param queueId the queueId to set - */ - public void setQueueId(int queueId) { - this.queueId = queueId; - } - - /** - * @return the queue's properties - */ - public List<OFQueueProp> getProperties() { - return properties; - } - - /** - * @param properties the properties to set - */ - public void setProperties(List<OFQueueProp> properties) { - this.properties = properties; - - this.length = U16.t(MINIMUM_LENGTH); - for (OFQueueProp prop : properties) { - this.length += prop.getLength(); - } - } - - /** - * @return the length - */ - public short getLength() { - return length; - } - - public void readFrom(ChannelBuffer data) { - this.queueId = data.readInt(); - this.length = data.readShort(); - data.readShort(); // pad - - int availLength = (this.length - MINIMUM_LENGTH); - this.properties.clear(); - - while (availLength > 0) { - OFQueueProp prop = new OFQueueProp(); - prop.readFrom(data); - properties.add(prop); - availLength -= prop.getLength(); - } - } - - public void writeTo(ChannelBuffer data) { - data.writeInt(queueId); - data.writeShort(length); - data.writeShort(0); // pad - - for (OFQueueProp prop : properties) { - prop.writeTo(data); - } - } - - @Override - public int hashCode() { - final int prime = 359; - int result = super.hashCode(); - result = prime * result + queueId; - result = prime * result + length; - result = prime * result + properties.hashCode(); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFPacketQueue)) { - return false; - } - OFPacketQueue other = (OFPacketQueue) obj; - if (queueId != other.queueId) { - return false; - } - if (! properties.equals(other.properties)) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFPhysicalPort.java b/src/main/java/org/openflow/protocol/OFPhysicalPort.java deleted file mode 100644 index 88de8f6570cb3d62370d1d2726fb6350fae36547..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPhysicalPort.java +++ /dev/null @@ -1,614 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.Arrays; - -import net.floodlightcontroller.core.web.serializers.ByteArrayMACSerializer; -import net.floodlightcontroller.core.web.serializers.UShortSerializer; -import net.floodlightcontroller.util.EnumBitmaps; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.HexString; - -/** - * Represents ofp_phy_port - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 25, 2010 - */ -public class OFPhysicalPort { - public final static int MINIMUM_LENGTH = 48; - public final static int OFP_ETH_ALEN = 6; - - public enum OFPortConfig implements EnumBitmaps.BitmapableEnum { - OFPPC_PORT_DOWN (1 << 0) { - @Override - public String toString() { - return "port-down (0x1)"; - } - }, - OFPPC_NO_STP (1 << 1) { - @Override - public String toString() { - return "no-stp (0x2)"; - } - }, - OFPPC_NO_RECV (1 << 2) { - @Override - public String toString() { - return "no-recv (0x4)"; - } - }, - OFPPC_NO_RECV_STP (1 << 3) { - @Override - public String toString() { - return "no-recv-stp (0x8)"; - } - }, - OFPPC_NO_FLOOD (1 << 4) { - @Override - public String toString() { - return "no-flood (0x10)"; - } - }, - OFPPC_NO_FWD (1 << 5) { - @Override - public String toString() { - return "no-fwd (0x20)"; - } - }, - OFPPC_NO_PACKET_IN (1 << 6) { - @Override - public String toString() { - return "no-pkt-in (0x40)"; - } - }, - OFPPC_BSN_MIRROR_DEST (1 << 31) { - @Override - public String toString() { - return "bsn-mirror-dest (0x80000000)"; - } - }; - - - protected int value; - - private OFPortConfig(int value) { - this.value = value; - } - - /** - * @return the value - */ - @Override - public int getValue() { - return value; - } - } - - public enum OFPortState { - OFPPS_LINK_DOWN (1 << 0, false) { - @Override - public String toString() { - return "link-down (0x1)"; - } - }, - OFPPS_STP_LISTEN (0 << 8, true) { - @Override - public String toString() { - return "listen (0x0)"; - } - }, - OFPPS_STP_LEARN (1 << 8, true) { - @Override - public String toString() { - return "learn-no-relay (0x100)"; - } - }, - OFPPS_STP_FORWARD (2 << 8, true) { - @Override - public String toString() { - return "forward (0x200)"; - } - }, - OFPPS_STP_BLOCK (3 << 8, true) { - @Override - public String toString() { - return "block-broadcast (0x300)"; - } - }, - OFPPS_STP_MASK (3 << 8, false) { // used for STP but not an STP state - @Override - public String toString() { - return "block-broadcast (0x300)"; - } - }; - - protected int value; - protected boolean isStpState; - - private OFPortState(int value, boolean isStpState) { - this.value = value; - this.isStpState = isStpState; - } - - /** - * Returns true if this constants represents one of the four STP - * states - * @return - */ - public boolean isStpState() { - return isStpState; - } - - /** - * return the STP state represented by the given integer. - * the returned value will have isStpState() == true - * @param state - * @return - */ - public static OFPortState getStpState(int state) { - // this ain't pretty - state = state & OFPortState.OFPPS_STP_MASK.getValue(); - for (OFPortState s: OFPortState.values()) { - if (!s.isStpState()) - continue; - if (state == s.getValue()) - return s; - } - return null; // will never happen - } - - public static boolean isPortDown(int state) { - if ((state & OFPPS_LINK_DOWN.getValue()) != 0) - return true; - else - return false; - } - - /** - * @return the value - */ - public int getValue() { - return value; - } - } - - /** - * Represents the speed of a port - */ - public enum PortSpeed { - /** no speed set */ - SPEED_NONE(0), - SPEED_10MB(10), - SPEED_100MB(100), - SPEED_1GB(1000), - SPEED_10GB(10000); - - private long speedInBps; - private PortSpeed(int speedInMbps) { - this.speedInBps = speedInMbps * 1000*1000; - } - - public long getSpeedBps() { - return this.speedInBps; - } - - public static PortSpeed max(PortSpeed s1, PortSpeed s2) { - return (s1.getSpeedBps() > s2.getSpeedBps()) ? s1 : s2; - } - - public static PortSpeed min(PortSpeed s1, PortSpeed s2) { - return (s1.getSpeedBps() < s2.getSpeedBps()) ? s1 : s2; - } - } - - public enum OFPortFeatures implements EnumBitmaps.BitmapableEnum { - OFPPF_10MB_HD (1 << 0, PortSpeed.SPEED_10MB) { - @Override - public String toString() { - return "10mb-hd (0x1)"; - } - }, - OFPPF_10MB_FD (1 << 1, PortSpeed.SPEED_10MB) { - @Override - public String toString() { - return "10mb-fd (0x2)"; - } - }, - OFPPF_100MB_HD (1 << 2, PortSpeed.SPEED_100MB) { - @Override - public String toString() { - return "100mb-hd (0x4)"; - } - }, - OFPPF_100MB_FD (1 << 3, PortSpeed.SPEED_100MB) { - @Override - public String toString() { - return "100mb-fd (0x8)"; - } - }, - OFPPF_1GB_HD (1 << 4, PortSpeed.SPEED_1GB) { - @Override - public String toString() { - return "1gb-hd (0x10)"; - } - }, - OFPPF_1GB_FD (1 << 5, PortSpeed.SPEED_1GB) { - @Override - public String toString() { - return "1gb-fd (0x20)"; - } - }, - OFPPF_10GB_FD (1 << 6, PortSpeed.SPEED_10GB) { - @Override - public String toString() { - return "10gb-fd (0x40)"; - } - }, - OFPPF_COPPER (1 << 7, PortSpeed.SPEED_NONE) { - @Override - public String toString() { - return "copper (0x80)"; - } - }, - OFPPF_FIBER (1 << 8, PortSpeed.SPEED_NONE) { - @Override - public String toString() { - return "fiber (0x100)"; - } - }, - OFPPF_AUTONEG (1 << 9, PortSpeed.SPEED_NONE) { - @Override - public String toString() { - return "autoneg (0x200)"; - } - }, - OFPPF_PAUSE (1 << 10, PortSpeed.SPEED_NONE) { - @Override - public String toString() { - return "pause (0x400)"; - } - }, - OFPPF_PAUSE_ASYM (1 << 11, PortSpeed.SPEED_NONE) { - @Override - public String toString() { - return "pause-asym (0x800)"; - } - }; - - protected int value; - protected PortSpeed speed; - - private OFPortFeatures(int value, PortSpeed speed) { - this.value = value; - if (speed == null) - throw new NullPointerException(); - this.speed = speed; - } - - /** - * @return the bitmap value for this constant - */ - @Override - public int getValue() { - return value; - } - - /** - * @return the port speed associated with this constant. If the - * constant doesn't represent a port speed it returns SPEED_NONE - */ - public PortSpeed getSpeed() { - return speed; - } - } - - protected short portNumber; - protected byte[] hardwareAddress; - protected String name; - protected int config; - protected int state; - protected int currentFeatures; - protected int advertisedFeatures; - protected int supportedFeatures; - protected int peerFeatures; - - /** - * @return the portNumber - */ - @JsonSerialize(using=UShortSerializer.class) - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - /** - * @return the hardwareAddress - */ - @JsonSerialize(using=ByteArrayMACSerializer.class) - public byte[] getHardwareAddress() { - return hardwareAddress; - } - - /** - * @param hardwareAddress the hardwareAddress to set - */ - public void setHardwareAddress(byte[] hardwareAddress) { - if (hardwareAddress.length != OFP_ETH_ALEN) - throw new RuntimeException("Hardware address must have length " - + OFP_ETH_ALEN); - this.hardwareAddress = hardwareAddress; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the config - */ - public int getConfig() { - return config; - } - - /** - * @param config the config to set - */ - public void setConfig(int config) { - this.config = config; - } - - /** - * @return the state - */ - public int getState() { - return state; - } - - /** - * @param state the state to set - */ - public void setState(int state) { - this.state = state; - } - - /** - * @return the currentFeatures - */ - public int getCurrentFeatures() { - return currentFeatures; - } - - /** - * @param currentFeatures the currentFeatures to set - */ - public void setCurrentFeatures(int currentFeatures) { - this.currentFeatures = currentFeatures; - } - - /** - * @return the advertisedFeatures - */ - public int getAdvertisedFeatures() { - return advertisedFeatures; - } - - /** - * @param advertisedFeatures the advertisedFeatures to set - */ - public void setAdvertisedFeatures(int advertisedFeatures) { - this.advertisedFeatures = advertisedFeatures; - } - - /** - * @return the supportedFeatures - */ - public int getSupportedFeatures() { - return supportedFeatures; - } - - /** - * @param supportedFeatures the supportedFeatures to set - */ - public void setSupportedFeatures(int supportedFeatures) { - this.supportedFeatures = supportedFeatures; - } - - /** - * @return the peerFeatures - */ - public int getPeerFeatures() { - return peerFeatures; - } - - /** - * @param peerFeatures the peerFeatures to set - */ - public void setPeerFeatures(int peerFeatures) { - this.peerFeatures = peerFeatures; - } - - /** - * Read this message off the wire from the specified ByteBuffer - * @param data - */ - public void readFrom(ChannelBuffer data) { - this.portNumber = data.readShort(); - if (this.hardwareAddress == null) - this.hardwareAddress = new byte[OFP_ETH_ALEN]; - data.readBytes(this.hardwareAddress); - byte[] name = new byte[16]; - data.readBytes(name); - // find the first index of 0 - int index = 0; - for (byte b : name) { - if (0 == b) - break; - ++index; - } - this.name = new String(Arrays.copyOf(name, index), - Charset.forName("ascii")); - this.config = data.readInt(); - this.state = data.readInt(); - this.currentFeatures = data.readInt(); - this.advertisedFeatures = data.readInt(); - this.supportedFeatures = data.readInt(); - this.peerFeatures = data.readInt(); - } - - /** - * Write this message's binary format to the specified ByteBuffer - * @param data - */ - public void writeTo(ChannelBuffer data) { - data.writeShort(this.portNumber); - data.writeBytes(hardwareAddress); - try { - byte[] name = this.name.getBytes("ASCII"); - if (name.length < 16) { - data.writeBytes(name); - for (int i = name.length; i < 16; ++i) { - data.writeByte((byte) 0); - } - } else { - data.writeBytes(name, 0, 15); - data.writeByte((byte) 0); - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - data.writeInt(this.config); - data.writeInt(this.state); - data.writeInt(this.currentFeatures); - data.writeInt(this.advertisedFeatures); - data.writeInt(this.supportedFeatures); - data.writeInt(this.peerFeatures); - } - - @Override - public int hashCode() { - final int prime = 307; - int result = 1; - result = prime * result + advertisedFeatures; - result = prime * result + config; - result = prime * result + currentFeatures; - result = prime * result + Arrays.hashCode(hardwareAddress); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + peerFeatures; - result = prime * result + portNumber; - result = prime * result + state; - result = prime * result + supportedFeatures; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFPhysicalPort)) { - return false; - } - OFPhysicalPort other = (OFPhysicalPort) obj; - if (advertisedFeatures != other.advertisedFeatures) { - return false; - } - if (config != other.config) { - return false; - } - if (currentFeatures != other.currentFeatures) { - return false; - } - if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) { - return false; - } - if (name == null) { - if (other.name != null) { - return false; - } - } else if (!name.equals(other.name)) { - return false; - } - if (peerFeatures != other.peerFeatures) { - return false; - } - if (portNumber != other.portNumber) { - return false; - } - if (state != other.state) { - return false; - } - if (supportedFeatures != other.supportedFeatures) { - return false; - } - return true; - } - - @Override - public String toString() { - String linkState, linkSpeed; - if ((state & OFPortState.OFPPS_LINK_DOWN.getValue()) != 0) { - linkState = "down"; - } else { - linkState = "up"; - } - if ((currentFeatures & OFPortFeatures.OFPPF_10GB_FD.getValue()) != 0) { - linkSpeed = "10G"; - } else if ((currentFeatures & OFPortFeatures.OFPPF_1GB_FD.getValue()) != 0) { - linkSpeed = "1G"; - } else if ((currentFeatures & OFPortFeatures.OFPPF_1GB_HD.getValue()) != 0) { - linkSpeed = "1G(half-duplex)"; - } else if ((currentFeatures & OFPortFeatures.OFPPF_100MB_FD.getValue()) != 0) { - linkSpeed = "100M"; - } else if ((currentFeatures & OFPortFeatures.OFPPF_100MB_HD.getValue()) != 0) { - linkSpeed = "100M(half-duplex)"; - } else if ((currentFeatures & OFPortFeatures.OFPPF_10MB_FD.getValue()) != 0) { - linkSpeed = "10M"; - } else if ((currentFeatures & OFPortFeatures.OFPPF_10MB_HD.getValue()) != 0) { - linkSpeed = "10M(half-duplex)"; - } else { - linkSpeed = "unknown"; - } - return "port " + name + " (" + portNumber + ")" + - ", mac " + HexString.toHexString(hardwareAddress) + - ", state " + linkState + - ", speed " + linkSpeed; - } -} diff --git a/src/main/java/org/openflow/protocol/OFPort.java b/src/main/java/org/openflow/protocol/OFPort.java deleted file mode 100644 index 93301bcb097486e454ec9c82bfd5768144d2cd77..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPort.java +++ /dev/null @@ -1,43 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -public enum OFPort { - OFPP_MAX ((short)0xff00), - OFPP_IN_PORT ((short)0xfff8), - OFPP_TABLE ((short)0xfff9), - OFPP_NORMAL ((short)0xfffa), - OFPP_FLOOD ((short)0xfffb), - OFPP_ALL ((short)0xfffc), - OFPP_CONTROLLER ((short)0xfffd), - OFPP_LOCAL ((short)0xfffe), - OFPP_NONE ((short)0xffff); - - protected short value; - - private OFPort(short value) { - this.value = value; - } - - /** - * @return the value - */ - public short getValue() { - return value; - } -} diff --git a/src/main/java/org/openflow/protocol/OFPortMod.java b/src/main/java/org/openflow/protocol/OFPortMod.java deleted file mode 100644 index 876e856700788c8a8d64b4ab37fe8febf87b5da7..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPortMod.java +++ /dev/null @@ -1,182 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents an ofp_port_mod message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFPortMod extends OFMessage { - public static int MINIMUM_LENGTH = 32; - - protected short portNumber; - protected byte[] hardwareAddress; - protected int config; - protected int mask; - protected int advertise; - - public OFPortMod() { - super(); - this.type = OFType.PORT_MOD; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - /** - * @return the hardwareAddress - */ - public byte[] getHardwareAddress() { - return hardwareAddress; - } - - /** - * @param hardwareAddress the hardwareAddress to set - */ - public void setHardwareAddress(byte[] hardwareAddress) { - if (hardwareAddress.length != OFPhysicalPort.OFP_ETH_ALEN) - throw new RuntimeException("Hardware address must have length " - + OFPhysicalPort.OFP_ETH_ALEN); - this.hardwareAddress = hardwareAddress; - } - - /** - * @return the config - */ - public int getConfig() { - return config; - } - - /** - * @param config the config to set - */ - public void setConfig(int config) { - this.config = config; - } - - /** - * @return the mask - */ - public int getMask() { - return mask; - } - - /** - * @param mask the mask to set - */ - public void setMask(int mask) { - this.mask = mask; - } - - /** - * @return the advertise - */ - public int getAdvertise() { - return advertise; - } - - /** - * @param advertise the advertise to set - */ - public void setAdvertise(int advertise) { - this.advertise = advertise; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.portNumber = data.readShort(); - if (this.hardwareAddress == null) - this.hardwareAddress = new byte[OFPhysicalPort.OFP_ETH_ALEN]; - data.readBytes(this.hardwareAddress); - this.config = data.readInt(); - this.mask = data.readInt(); - this.advertise = data.readInt(); - data.readInt(); // pad - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.portNumber); - data.writeBytes(this.hardwareAddress); - data.writeInt(this.config); - data.writeInt(this.mask); - data.writeInt(this.advertise); - data.writeInt(0); // pad - } - - @Override - public int hashCode() { - final int prime = 311; - int result = super.hashCode(); - result = prime * result + advertise; - result = prime * result + config; - result = prime * result + Arrays.hashCode(hardwareAddress); - result = prime * result + mask; - result = prime * result + portNumber; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFPortMod)) { - return false; - } - OFPortMod other = (OFPortMod) obj; - if (advertise != other.advertise) { - return false; - } - if (config != other.config) { - return false; - } - if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) { - return false; - } - if (mask != other.mask) { - return false; - } - if (portNumber != other.portNumber) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFPortStatus.java b/src/main/java/org/openflow/protocol/OFPortStatus.java deleted file mode 100644 index b7a3158ceee2ef7d6cc99086089cbe8e4203531f..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFPortStatus.java +++ /dev/null @@ -1,144 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents an ofp_port_status message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFPortStatus extends OFMessage { - public static int MINIMUM_LENGTH = 64; - - public enum OFPortReason { - OFPPR_ADD((byte)0), - OFPPR_DELETE((byte)1), - OFPPR_MODIFY((byte)2); - - private byte reason; - - private OFPortReason(byte reason) { - this.reason = reason; - } - - public byte getReasonCode() { - return this.reason; - } - - public static OFPortReason fromReasonCode(byte reason) { - for (OFPortReason r: OFPortReason.values()) { - if (r.getReasonCode() == reason) - return r; - } - return null; - } - } - - protected byte reason; - protected OFPhysicalPort desc; - - /** - * @return the reason - */ - public byte getReason() { - return reason; - } - - /** - * @param reason the reason to set - */ - public void setReason(byte reason) { - this.reason = reason; - } - - /** - * @return the desc - */ - public OFPhysicalPort getDesc() { - return desc; - } - - /** - * @param desc the desc to set - */ - public void setDesc(OFPhysicalPort desc) { - this.desc = desc; - } - - public OFPortStatus() { - super(); - this.type = OFType.PORT_STATUS; - this.length = U16.t(MINIMUM_LENGTH); - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.reason = data.readByte(); - data.readerIndex(data.readerIndex() + 7); // skip 7 bytes of padding - if (this.desc == null) - this.desc = new OFPhysicalPort(); - this.desc.readFrom(data); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeByte(this.reason); - for (int i = 0; i < 7; ++i) - data.writeByte((byte) 0); - this.desc.writeTo(data); - } - - @Override - public int hashCode() { - final int prime = 313; - int result = super.hashCode(); - result = prime * result + ((desc == null) ? 0 : desc.hashCode()); - result = prime * result + reason; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFPortStatus)) { - return false; - } - OFPortStatus other = (OFPortStatus) obj; - if (desc == null) { - if (other.desc != null) { - return false; - } - } else if (!desc.equals(other.desc)) { - return false; - } - if (reason != other.reason) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java b/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java deleted file mode 100644 index 62be90d59f4106e8a6581dcf81bc5153cee83ce1..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java +++ /dev/null @@ -1,125 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.protocol; - -import java.util.ArrayList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents an ofp_queue_get_config_request message - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFQueueGetConfigReply extends OFMessage { - public static int MINIMUM_LENGTH = 16; - - protected short portNumber; - protected List<OFPacketQueue> queues = new ArrayList<OFPacketQueue>(); - - public OFQueueGetConfigReply() { - super(); - this.type = OFType.QUEUE_GET_CONFIG_REPLY; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - /** - * @return the port's queues - */ - public List<OFPacketQueue> getQueues() { - return queues; - } - - /** - * @param queues the queues to set - */ - public void setQueues(List<OFPacketQueue> queues) { - this.queues.clear(); - this.queues.addAll(queues); - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.portNumber = data.readShort(); - data.readInt(); // pad - data.readShort(); // pad - - int availLength = (this.length - MINIMUM_LENGTH); - this.queues.clear(); - - while (availLength > 0) { - OFPacketQueue queue = new OFPacketQueue(); - queue.readFrom(data); - queues.add(queue); - availLength -= queue.getLength(); - } - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.portNumber); - data.writeInt(0); // pad - data.writeShort(0); // pad - - for (OFPacketQueue queue : queues) { - queue.writeTo(data); - } - } - - @Override - public int hashCode() { - final int prime = 349; - int result = super.hashCode(); - result = prime * result + portNumber; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFQueueGetConfigReply)) { - return false; - } - OFQueueGetConfigReply other = (OFQueueGetConfigReply) obj; - if (portNumber != other.portNumber) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java b/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java deleted file mode 100644 index cbb4a3734b9bc6510362afa237b6121398d9e4cd..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java +++ /dev/null @@ -1,95 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * Represents an ofp_queue_get_config_request message - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFQueueGetConfigRequest extends OFMessage { - public static int MINIMUM_LENGTH = 12; - - protected short portNumber; - - public OFQueueGetConfigRequest(short portNumber) { - super(); - this.type = OFType.QUEUE_GET_CONFIG_REQUEST; - this.length = U16.t(MINIMUM_LENGTH); - this.portNumber = portNumber; - } - - public OFQueueGetConfigRequest() { - this((short) 0); - } - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.portNumber = data.readShort(); - data.readShort(); // pad - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.portNumber); - data.writeShort(0); // pad - } - - @Override - public int hashCode() { - final int prime = 347; - int result = super.hashCode(); - result = prime * result + portNumber; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFQueueGetConfigRequest)) { - return false; - } - OFQueueGetConfigRequest other = (OFQueueGetConfigRequest) obj; - if (portNumber != other.portNumber) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFQueueProp.java b/src/main/java/org/openflow/protocol/OFQueueProp.java deleted file mode 100644 index 2e12224bbbf1a7baf86c4a61eac9c3ab32f72580..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFQueueProp.java +++ /dev/null @@ -1,175 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -public class OFQueueProp { - private int NONE_MINIMUM_LENGTH = 8; - private int RATE_MINIMUM_LENGTH = 16; - - public enum OFQueuePropType { - OFPQT_NONE (0), - OFPQT_MIN_RATE (1), - OFPQT_MAX_RATE (2); - - protected int value; - - private OFQueuePropType(int value) { - this.value = value; - } - - /** - * @return the value - */ - public int getValue() { - return value; - } - - public static OFQueuePropType fromShort(short x) { - switch (x) { - case 0: - return OFPQT_NONE; - case 1: - return OFPQT_MIN_RATE; - case 2: - return OFPQT_MAX_RATE; - } - return null; - } - } - - protected OFQueuePropType type; - protected short length; - protected short rate = -1; // not valid if type == OFPQT_NONE - - public OFQueueProp() { - this.type = OFQueuePropType.OFPQT_NONE; - this.length = U16.t(NONE_MINIMUM_LENGTH); - } - - /** - * @return the type - */ - public OFQueuePropType getType() { - return type; - } - - /** - * @param type the type to set - */ - public void setType(OFQueuePropType type) { - this.type = type; - - switch (type) { - case OFPQT_NONE: - this.length = U16.t(NONE_MINIMUM_LENGTH); - break; - case OFPQT_MIN_RATE: - this.length = U16.t(RATE_MINIMUM_LENGTH); - break; - case OFPQT_MAX_RATE: - this.length = U16.t(RATE_MINIMUM_LENGTH); - break; - } - } - - /** - * @return the rate - */ - public short getRate() { - return rate; - } - - /** - * @param rate the rate to set - */ - public void setRate(short rate) { - this.rate = rate; - } - - /** - * @return the length - */ - public short getLength() { - return length; - } - - public void readFrom(ChannelBuffer data) { - this.type = OFQueuePropType.fromShort(data.readShort()); - this.length = data.readShort(); - data.readInt(); // pad - - if (this.type == OFQueuePropType.OFPQT_MIN_RATE || - this.type == OFQueuePropType.OFPQT_MAX_RATE) { - assert(this.length == RATE_MINIMUM_LENGTH); - - this.rate = data.readShort(); - data.readInt(); // pad - data.readShort(); // pad - } else { - assert(this.length == NONE_MINIMUM_LENGTH); - } - } - - public void writeTo(ChannelBuffer data) { - data.writeShort(this.type.getValue()); - data.writeShort(this.length); - data.writeInt(0); // pad - - if (this.type == OFQueuePropType.OFPQT_MIN_RATE || - this.type == OFQueuePropType.OFPQT_MAX_RATE) { - data.writeShort(this.rate); - data.writeInt(0); // pad - data.writeShort(0); // pad - } - } - - @Override - public int hashCode() { - final int prime = 353; - int result = super.hashCode(); - result = prime * result + type.getValue(); - result = prime * result + rate; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFQueueProp)) { - return false; - } - OFQueueProp other = (OFQueueProp) obj; - if (type != other.type) { - return false; - } - if (type == OFQueuePropType.OFPQT_MIN_RATE || - type == OFQueuePropType.OFPQT_MAX_RATE) { - if (rate != other.rate) { - return false; - } - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFSetConfig.java b/src/main/java/org/openflow/protocol/OFSetConfig.java deleted file mode 100644 index 4b2356476e5b1b7af304e92d239ab14dd2a2e29b..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFSetConfig.java +++ /dev/null @@ -1,29 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -/** - * Represents an OFPT_SET_CONFIG type message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFSetConfig extends OFSwitchConfig { - public OFSetConfig() { - super(); - this.type = OFType.SET_CONFIG; - } -} diff --git a/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java b/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java deleted file mode 100644 index e5a9c01e0093e29055bb75943909860490347e43..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java +++ /dev/null @@ -1,180 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.factory.OFStatisticsFactory; -import org.openflow.protocol.factory.OFStatisticsFactoryAware; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; - - -/** - * Base class for statistics requests/replies - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 27, 2010 - */ -public abstract class OFStatisticsMessageBase extends OFMessage implements - OFStatisticsFactoryAware { - public static int MINIMUM_LENGTH = 12; - - protected OFStatisticsFactory statisticsFactory; - protected OFStatisticsType statisticType; - protected short flags; - - // TODO: this should be List<? extends OFStatistics>, to - // allow for type safe assignments of lists of specific message - protected List<? extends OFStatistics> statistics; - - /** - * @return the statisticType - */ - public OFStatisticsType getStatisticType() { - return statisticType; - } - - /** - * @param statisticType the statisticType to set - */ - public void setStatisticType(OFStatisticsType statisticType) { - this.statisticType = statisticType; - } - - /** - * @return the flags - */ - public short getFlags() { - return flags; - } - - /** - * @param flags the flags to set - */ - public void setFlags(short flags) { - this.flags = flags; - } - - /** - * @return the statistics - */ - public List<? extends OFStatistics> getStatistics() { - return statistics; - } - - /** - * return the first statistics request in the list of statistics, for - * statistics messages that expect exactly one message in their body (e.g., - * flow stats request, port statsrequest) - * - * @return the first and only element in the list of statistics - * @throw IllegalArgumentException if the list does not contain exactly one - * element - */ - public OFStatistics getFirstStatistics() { - if (statistics == null ) { - throw new IllegalArgumentException("Invariant violation: statistics message of type "+statisticType+" is null"); - } - if (statistics.size() != 1) { - throw new IllegalArgumentException("Invariant violation: statistics message of type "+statisticType+" contains "+statistics.size() +" statreq/reply messages in its body (should be 1)"); - } - - return statistics.get(0); - } - - /** - * @param statistics the statistics to set - */ - public void setStatistics(List<? extends OFStatistics> statistics) { - this.statistics = statistics; - } - - @Override - public void setStatisticsFactory(OFStatisticsFactory statisticsFactory) { - this.statisticsFactory = statisticsFactory; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.statisticType = OFStatisticsType.valueOf(data.readShort(), this - .getType()); - this.flags = data.readShort(); - if (this.statisticsFactory == null) - throw new RuntimeException("OFStatisticsFactory not set"); - this.statistics = statisticsFactory.parseStatistics(this.getType(), - this.statisticType, data, super.getLengthU() - MINIMUM_LENGTH); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.statisticType.getTypeValue()); - data.writeShort(this.flags); - if (this.statistics != null) { - for (OFStatistics statistic : this.statistics) { - statistic.writeTo(data); - } - } - } - - @Override - public int hashCode() { - final int prime = 317; - int result = super.hashCode(); - result = prime * result + flags; - result = prime * result - + ((statisticType == null) ? 0 : statisticType.hashCode()); - result = prime * result - + ((statistics == null) ? 0 : statistics.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFStatisticsMessageBase)) { - return false; - } - OFStatisticsMessageBase other = (OFStatisticsMessageBase) obj; - if (flags != other.flags) { - return false; - } - if (statisticType == null) { - if (other.statisticType != null) { - return false; - } - } else if (!statisticType.equals(other.statisticType)) { - return false; - } - if (statistics == null) { - if (other.statistics != null) { - return false; - } - } else if (!statistics.equals(other.statistics)) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFStatisticsReply.java b/src/main/java/org/openflow/protocol/OFStatisticsReply.java deleted file mode 100644 index ddc7267425ab98431c350d393253623c894bed4f..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFStatisticsReply.java +++ /dev/null @@ -1,46 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - -/** - * Represents an ofp_stats_reply message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFStatisticsReply extends OFStatisticsMessageBase { - public enum OFStatisticsReplyFlags { - REPLY_MORE (1 << 0); - - protected short type; - - OFStatisticsReplyFlags(int type) { - this.type = (short) type; - } - - public short getTypeValue() { - return type; - } - } - - public OFStatisticsReply() { - super(); - this.type = OFType.STATS_REPLY; - this.length = U16.t(OFStatisticsMessageBase.MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFStatisticsRequest.java b/src/main/java/org/openflow/protocol/OFStatisticsRequest.java deleted file mode 100644 index d1d8010e921a5f7918ac3869af387e2b12185016..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFStatisticsRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.openflow.util.U16; - -/** - * Represents an ofp_stats_request message - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFStatisticsRequest extends OFStatisticsMessageBase { - public OFStatisticsRequest() { - super(); - this.type = OFType.STATS_REQUEST; - this.length = U16.t(OFStatisticsMessageBase.MINIMUM_LENGTH); - } -} diff --git a/src/main/java/org/openflow/protocol/OFSwitchConfig.java b/src/main/java/org/openflow/protocol/OFSwitchConfig.java deleted file mode 100644 index e04e3fa60fe65a1f85bdc767588e63f45990efc2..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFSwitchConfig.java +++ /dev/null @@ -1,118 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Base class representing ofp_switch_config based messages - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public abstract class OFSwitchConfig extends OFMessage { - public static int MINIMUM_LENGTH = 12; - - public enum OFConfigFlags { - OFPC_FRAG_NORMAL, - OFPC_FRAG_DROP, - OFPC_FRAG_REASM, - OFPC_FRAG_MASK - } - - protected short flags; - protected short missSendLength; - - public OFSwitchConfig() { - super(); - super.setLengthU(MINIMUM_LENGTH); - } - - /** - * @return the flags - */ - public short getFlags() { - return flags; - } - - /** - * @param flags the flags to set - */ - public OFSwitchConfig setFlags(short flags) { - this.flags = flags; - return this; - } - - /** - * @return the missSendLength - */ - public short getMissSendLength() { - return missSendLength; - } - - /** - * @param missSendLength the missSendLength to set - */ - public OFSwitchConfig setMissSendLength(short missSendLength) { - this.missSendLength = missSendLength; - return this; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.flags = data.readShort(); - this.missSendLength = data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.flags); - data.writeShort(this.missSendLength); - } - - @Override - public int hashCode() { - final int prime = 331; - int result = super.hashCode(); - result = prime * result + flags; - result = prime * result + missSendLength; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFSwitchConfig)) { - return false; - } - OFSwitchConfig other = (OFSwitchConfig) obj; - if (flags != other.flags) { - return false; - } - if (missSendLength != other.missSendLength) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/OFType.java b/src/main/java/org/openflow/protocol/OFType.java deleted file mode 100644 index f1c81e2884b0f850efe420aa54c1fe810869442e..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFType.java +++ /dev/null @@ -1,249 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.lang.reflect.Constructor; - -/** - * List of OpenFlow types and mappings to wire protocol value and derived - * classes - * - * @author Rob Sherwood (rob.sherwood@stanford.edu) - * @author David Erickson (daviderickson@cs.stanford.edu) - * - */ -public enum OFType { - HELLO (0, OFHello.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFHello(); - }}), - ERROR (1, OFError.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFError(); - }}), - ECHO_REQUEST (2, OFEchoRequest.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFEchoRequest(); - }}), - ECHO_REPLY (3, OFEchoReply.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFEchoReply(); - }}), - VENDOR (4, OFVendor.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFVendor(); - }}), - FEATURES_REQUEST (5, OFFeaturesRequest.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFFeaturesRequest(); - }}), - FEATURES_REPLY (6, OFFeaturesReply.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFFeaturesReply(); - }}), - GET_CONFIG_REQUEST (7, OFGetConfigRequest.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFGetConfigRequest(); - }}), - GET_CONFIG_REPLY (8, OFGetConfigReply.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFGetConfigReply(); - }}), - SET_CONFIG (9, OFSetConfig.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFSetConfig(); - }}), - PACKET_IN (10, OFPacketIn.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFPacketIn(); - }}), - FLOW_REMOVED (11, OFFlowRemoved.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFFlowRemoved(); - }}), - PORT_STATUS (12, OFPortStatus.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFPortStatus(); - }}), - PACKET_OUT (13, OFPacketOut.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFPacketOut(); - }}), - FLOW_MOD (14, OFFlowMod.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFFlowMod(); - }}), - PORT_MOD (15, OFPortMod.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFPortMod(); - }}), - STATS_REQUEST (16, OFStatisticsRequest.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFStatisticsRequest(); - }}), - STATS_REPLY (17, OFStatisticsReply.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFStatisticsReply(); - }}), - BARRIER_REQUEST (18, OFBarrierRequest.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFBarrierRequest(); - }}), - BARRIER_REPLY (19, OFBarrierReply.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFBarrierReply(); - }}), - QUEUE_GET_CONFIG_REQUEST (20, OFQueueGetConfigRequest.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFQueueGetConfigRequest(); - }}), - QUEUE_GET_CONFIG_REPLY (21, OFQueueGetConfigReply.class, new Instantiable<OFMessage>() { - @Override - public OFMessage instantiate() { - return new OFQueueGetConfigReply(); - }}); - - static OFType[] mapping; - - protected Class<? extends OFMessage> clazz; - protected Constructor<? extends OFMessage> constructor; - protected Instantiable<OFMessage> instantiable; - protected byte type; - - /** - * Store some information about the OpenFlow type, including wire protocol - * type number, length, and derived class - * - * @param type Wire protocol number associated with this OFType - * @param clazz The Java class corresponding to this type of OpenFlow - * message - * @param instantiator An Instantiator<OFMessage> implementation that creates an - * instance of the specified OFMessage - */ - OFType(int type, Class<? extends OFMessage> clazz, Instantiable<OFMessage> instantiator) { - this.type = (byte) type; - this.clazz = clazz; - this.instantiable = instantiator; - try { - this.constructor = clazz.getConstructor(new Class[]{}); - } catch (Exception e) { - throw new RuntimeException( - "Failure getting constructor for class: " + clazz, e); - } - OFType.addMapping(this.type, this); - } - - /** - * Adds a mapping from type value to OFType enum - * - * @param i OpenFlow wire protocol type - * @param t type - */ - static public void addMapping(byte i, OFType t) { - if (mapping == null) - mapping = new OFType[32]; - OFType.mapping[i] = t; - } - - /** - * Remove a mapping from type value to OFType enum - * - * @param i OpenFlow wire protocol type - */ - static public void removeMapping(byte i) { - OFType.mapping[i] = null; - } - - /** - * Given a wire protocol OpenFlow type number, return the OFType associated - * with it - * - * @param i wire protocol number - * @return OFType enum type - */ - - static public OFType valueOf(Byte i) { - return OFType.mapping[i]; - } - - /** - * @return Returns the wire protocol value corresponding to this OFType - */ - public byte getTypeValue() { - return this.type; - } - - /** - * @return return the OFMessage subclass corresponding to this OFType - */ - public Class<? extends OFMessage> toClass() { - return clazz; - } - - /** - * Returns the no-argument Constructor of the implementation class for - * this OFType - * @return the constructor - */ - public Constructor<? extends OFMessage> getConstructor() { - return constructor; - } - - /** - * Returns a new instance of the OFMessage represented by this OFType - * @return the new object - */ - public OFMessage newInstance() { - return instantiable.instantiate(); - } - - /** - * @return the instantiable - */ - public Instantiable<OFMessage> getInstantiable() { - return instantiable; - } - - /** - * @param instantiable the instantiable to set - */ - public void setInstantiable(Instantiable<OFMessage> instantiable) { - this.instantiable = instantiable; - } -} diff --git a/src/main/java/org/openflow/protocol/OFVendor.java b/src/main/java/org/openflow/protocol/OFVendor.java deleted file mode 100644 index 8ecb862becf1a2ba52d4c0ddabeb8474a5c58ef5..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/OFVendor.java +++ /dev/null @@ -1,131 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; -import org.openflow.protocol.factory.OFVendorDataFactory; -import org.openflow.protocol.factory.OFVendorDataFactoryAware; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Represents ofp_vendor_header - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFVendor extends OFMessage implements OFVendorDataFactoryAware { - public static int MINIMUM_LENGTH = 12; - - protected int vendor; - protected OFVendorData vendorData; - protected OFVendorDataFactory vendorDataFactory; - - public OFVendor() { - super(); - this.type = OFType.VENDOR; - this.length = U16.t(MINIMUM_LENGTH); - } - - /** - * @return the vendor - */ - public int getVendor() { - return vendor; - } - - /** - * @param vendor the vendor to set - */ - public void setVendor(int vendor) { - this.vendor = vendor; - } - - /** - * @return the data - */ - public OFVendorData getVendorData() { - return vendorData; - } - - /** - * @param data the data to set - */ - public void setVendorData(OFVendorData vendorData) { - this.vendorData = vendorData; - } - - @Override - public void setVendorDataFactory(OFVendorDataFactory vendorDataFactory) { - this.vendorDataFactory = vendorDataFactory; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.vendor = data.readInt(); - if (vendorDataFactory == null) - throw new RuntimeException("OFVendorDataFactory not set"); - - this.vendorData = vendorDataFactory.parseVendorData(vendor, - data, super.getLengthU() - MINIMUM_LENGTH); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeInt(this.vendor); - if (vendorData != null) - vendorData.writeTo(data); - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 337; - int result = super.hashCode(); - result = prime * result + vendor; - if (vendorData != null) - result = prime * result + vendorData.hashCode(); - return result; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - OFVendor other = (OFVendor) obj; - if (vendor != other.vendor) - return false; - if (vendorData == null) { - if (other.vendorData != null) { - return false; - } - } else if (!vendorData.equals(other.vendorData)) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/Wildcards.java b/src/main/java/org/openflow/protocol/Wildcards.java deleted file mode 100644 index 4b0ea07b5146e45c8ab69102487437ee7ff24820..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/Wildcards.java +++ /dev/null @@ -1,603 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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 org.openflow.protocol; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.List; - -import com.google.common.base.Joiner; - -/** - * a more user friendly representation of the wildcards bits in an OpenFlow - * match. The Wildcards object is - * <ul> - * <li>immutable (i.e., threadsafe)</li> - * <li>instance managed (don't instantiate it yourself), instead call "of"</li> - * <ul> - * <p> - * You can construct a Wildcard object from either its integer representation - * </p> - * <code> - * Wildcard.of(0x3820e0); - * </code> - * <p> - * Or start with either an empty or full wildcard, and select/unselect foo. - * </p> - * <code> - * Wildcard w = Wildcards.NONE - * .set(Flag.DL_SRC, Flag. DL_DST, Flag.DL_VLAN_PCP) - * .setNwDstMask(8) - * .setNwSrcMask(8); - * </code> - * <p> - * <b>Remember:</b> Wildcards objects are immutable. set... operations have - * <b>NO EFFECT</b> on the current wildcard object. You HAVE to use the returned - * changed object. - * </p> - * - * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> - */ -public class Wildcards { - - public final static Wildcards FULL = new Wildcards(OFMatch.OFPFW_ALL_SANITIZED); - private static final int FULL_INT = FULL.getInt(); - - public final static Wildcards EXACT = new Wildcards(0); - - // floodlight common case: matches on inport + l2 - public final static int INT_INPORT_L2_MATCH = 0x3820e0; - public final static Wildcards INPORT_L2_MATCH = new Wildcards( - INT_INPORT_L2_MATCH); - - /** - * enum type for the binary flags that can be set in the wildcards field of - * an OFMatch. Replaces the unwieldy c-ish int constants in OFMatch. - */ - public static enum Flag { - IN_PORT(OFMatch.OFPFW_IN_PORT), /* Switch input port. */ - DL_VLAN(OFMatch.OFPFW_DL_VLAN), /* VLAN id. */ - DL_SRC(OFMatch.OFPFW_DL_SRC), /* Ethernet source address. */ - DL_DST(OFMatch.OFPFW_DL_DST), /* Ethernet destination addr */ - DL_TYPE(OFMatch.OFPFW_DL_TYPE), /* Ethernet frame type. */ - NW_PROTO(OFMatch.OFPFW_NW_PROTO), /* IP protocol. */ - TP_SRC(OFMatch.OFPFW_TP_SRC), /* TCP/UDP source port. */ - TP_DST(OFMatch.OFPFW_TP_DST), /* TCP/UDP destination port. */ - DL_VLAN_PCP(OFMatch.OFPFW_DL_VLAN_PCP), /* VLAN priority. */ - NW_SRC(-1) { /* - * virtual NW_SRC flag => translates to the strange 6 bits - * in the header - */ - @Override - boolean isBolean() { - return false; - } - - @Override - int getInt(int flags) { - return ((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT); - } - - @Override - int setInt(int flags, int srcMask) { - return (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | (srcMask << OFMatch.OFPFW_NW_SRC_SHIFT); - } - - @Override - int wildcard(int flags) { - return flags & ~OFMatch.OFPFW_NW_SRC_MASK; - } - - @Override - int matchOn(int flags) { - return flags | OFMatch.OFPFW_NW_SRC_ALL; - } - - @Override - boolean isPartiallyOn(int flags) { - int intValue = getInt(flags); - return intValue > 0 && intValue < 32; - } - - @Override - boolean isFullyOn(int flags) { - return getInt(flags) >= 32; - } - - }, - NW_DST(-1) { /* - * virtual NW_SRC flag => translates to the strange 6 bits - * in the header - */ - @Override - boolean isBolean() { - return false; - } - - @Override - int getInt(int flags) { - return ((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT); - } - - @Override - int setInt(int flags, int srcMask) { - return (flags & ~OFMatch.OFPFW_NW_DST_MASK) | (srcMask << OFMatch.OFPFW_NW_DST_SHIFT); - } - - @Override - int wildcard(int flags) { - return flags & ~OFMatch.OFPFW_NW_DST_MASK; - } - - @Override - int matchOn(int flags) { - return flags | OFMatch.OFPFW_NW_DST_ALL; - } - - @Override - boolean isFullyOn(int flags) { - return getInt(flags) >= 32; - } - }, - NW_TOS(OFMatch.OFPFW_NW_TOS); /* IP ToS (DSCP field, 6 bits). */ - - final int bitPosition; - - Flag(int bitPosition) { - this.bitPosition = bitPosition; - } - - /** - * @return a modified OF-1.0 flags field with this flag cleared (match - * on this field) - */ - int matchOn(int flags) { - return flags & ~this.bitPosition; - } - - /** - * @return a modified OF-1.0 flags field with this flag set (wildcard - * this field) - */ - int wildcard(int flags) { - return flags | this.bitPosition; - } - - /** - * @return true iff this is a true boolean flag that can either be off - * or on.True in OF-1.0 for all fields except NW_SRC and NW_DST - */ - boolean isBolean() { - return false; - } - - /** - * @return true iff this wildcard field is currently 'partially on'. - * Always false for true Boolean Flags. Can be true in OF-1.0 - * for NW_SRC, NW_DST. - */ - boolean isPartiallyOn(int flags) { - return false; - } - - /** - * @return true iff this wildcard field currently fully on (fully - * wildcarded). Equivalent to the boolean flag being set in the - * bitmask for bit flags, and to the wildcarded bit length set - * to >=32 for NW_SRC and NW_DST - * @param flags - * @return - */ - boolean isFullyOn(int flags) { - return (flags & this.bitPosition) != 0; - } - - /** - * set the integer representation of this flag. only for NW_SRC and - * NW_DST - */ - int setInt(int flags, int srcMask) { - throw new UnsupportedOperationException(); - } - - /** - * set the integer representation of this flag. only for NW_SRC and - * NW_DST - */ - int getInt(int flags) { - throw new UnsupportedOperationException(); - } - - - } - - private final int flags; - - /** private constructor. use Wildcard.of() instead */ - private Wildcards(int flags) { - this.flags = flags; - } - - /** - * return a wildcard object matching the given int flags. May reuse / cache - * frequently used wildcard instances. Don't rely on it though (use equals - * not ==). - * - * @param flags - * @return - */ - public static Wildcards of(int paramFlags) { - int flags = sanitizeInt(paramFlags); - switch(flags) { - case 0x0000: - return EXACT; - case OFMatch.OFPFW_ALL_SANITIZED: - return FULL; - case INT_INPORT_L2_MATCH: - return INPORT_L2_MATCH; - default: - return new Wildcards(flags); - } - } - - /** convience method return a wildcard for exactly one set flag */ - public static Wildcards of(Wildcards.Flag setFlag) { - return Wildcards.of(setFlag.wildcard(0)); - } - - /** convience method return a wildcard for exactly two set flags */ - public static Wildcards of(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) { - return Wildcards.of(setFlag.wildcard(setFlag2.wildcard(0))); - } - - /** convience method return a wildcard for an arbitrary number of set flags */ - public static Wildcards of(Wildcards.Flag... setFlags) { - int flags = 0; - for (Wildcards.Flag flag : setFlags) - flags = flag.wildcard(0); - return Wildcards.of(flags); - } - - /** convience method return a wildcards for ofmatches that match on one flag */ - public static Wildcards ofMatches(Wildcards.Flag setFlag) { - return Wildcards.of(setFlag.matchOn(FULL_INT)); - } - - /** - * convience method return a wildcard for for an ofmatch that match on two - * flags - */ - public static Wildcards ofMatches(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) { - return Wildcards.of(setFlag.matchOn(setFlag2.matchOn(FULL_INT))); - } - - /** - * convience method return a wildcard for an ofmatch that amtch on an - * arbitrary number of set flags - */ - public static Wildcards ofMatches(Wildcards.Flag... setFlags) { - int flags = FULL_INT; - for (Wildcards.Flag flag : setFlags) - flags = flag.matchOn(flags); - return Wildcards.of(flags); - } - - /** - * return a Wildcards object that has the given flags set - * <p> - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - */ - public Wildcards wildcard(Wildcards.Flag flag) { - int flags = flag.wildcard(this.flags); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcards object that has the given flags set - * <p> - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - */ - public Wildcards wildcard(Wildcards.Flag flag, Wildcards.Flag flag2) { - int flags = flag.wildcard(flag2.wildcard(this.flags)); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcards object that has the given flags wildcarded - * <p> - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - */ - public Wildcards wildcard(Wildcards.Flag... setFlags) { - int flags = this.flags; - for (Wildcards.Flag flag : setFlags) - flags = flag.wildcard(flags); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcards object that matches on exactly the given flag - * <p> - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - */ - public Wildcards matchOn(Wildcards.Flag flag) { - int flags = flag.matchOn(this.flags); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcards object that matches on exactly the given flags - * <p> - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - */ - public Wildcards matchOn(Wildcards.Flag flag, Wildcards.Flag flag2) { - int flags = flag.matchOn(flag2.matchOn(this.flags)); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcards object that matches on exactly the given flags - * <p> - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - */ - public Wildcards matchOn(Wildcards.Flag... setFlags) { - int flags = this.flags; - for (Wildcards.Flag flag : setFlags) - flags = flag.matchOn(flags); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return the nw src mask in normal CIDR style, e.g., 8 means x.x.x.x/8 - * means 8 bits wildcarded - */ - public int getNwSrcMask() { - return Math.max(0, 32 - Flag.NW_SRC.getInt(flags)); - } - - /** - * return the nw dst mask in normal CIDR style, e.g., 8 means x.x.x.x/8 - * means 8 bits wildcarded - */ - public int getNwDstMask() { - return Math.max(0, 32 - Flag.NW_DST.getInt(flags)); - } - - /** - * return a Wildcard object that has the given nwSrcCidrMask set. - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - * - * @param srcCidrMask - * source mask to set in <b>normal CIDR notation</b>, i.e., 8 - * means x.x.x.x/8 - * @return a modified object - */ - public Wildcards withNwSrcMask(int srcCidrMask) { - int flags = Flag.NW_SRC.setInt(this.flags, Math.max(0, 32 - srcCidrMask)); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcard object that has the given nwDstCidrMask set. - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - * - * @param dstCidrMask - * dest mask to set in <b>normal CIDR notation</b>, i.e., 8 means - * x.x.x.x/8 - * @return a modified object - */ - public Wildcards withNwDstMask(int dstCidrMask) { - int flags = Flag.NW_DST.setInt(this.flags, Math.max(0, 32 - dstCidrMask)); - if (flags == this.flags) - return this; - else - return new Wildcards(flags); - } - - /** - * return a Wildcard object that is inverted to this wildcard object. - * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays - * unmodified. </b> - * @return a modified object - */ - public Wildcards inverted() { - return Wildcards.of(flags ^ OFMatch.OFPFW_ALL_SANITIZED); - } - - public boolean isWildcarded(Flag flag) { - return flag.isFullyOn(flags); - } - - /** - * return all wildcard flags that are fully wildcarded as an EnumSet. Do not - * modify. Note: some flags (like NW_SRC and NW_DST) that are partially - * wildcarded are not returned in this set. - * - * @return the EnumSet of wildcards - */ - public EnumSet<Wildcards.Flag> getWildcardedFlags() { - EnumSet<Wildcards.Flag> res = EnumSet.noneOf(Wildcards.Flag.class); - for (Wildcards.Flag flag : Flag.values()) { - if (flag.isFullyOn(flags)) { - res.add(flag); - } - } - return res; - } - - /** return the OpenFlow 'wire' integer representation of these wildcards */ - public int getInt() { - return flags; - } - - /** - * return the OpenFlow 'wire' integer representation of these wildcards. - * Sanitize nw_src and nw_dst to be max. 32 (values > 32 are technically - * possible, but don't make semantic sense) - */ - public static int sanitizeInt(int flags) { - if (((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT) > 32) { - flags = (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | OFMatch.OFPFW_NW_SRC_ALL; - } - if (((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT) > 32) { - flags = (flags & ~OFMatch.OFPFW_NW_DST_MASK) | OFMatch.OFPFW_NW_DST_ALL; - } - return flags; - } - - /** - * is this a wildcard set that has all flags set + and full (/0) nw_src and - * nw_dst wildcarding ? - */ - public boolean isFull() { - return flags == OFMatch.OFPFW_ALL || flags == OFMatch.OFPFW_ALL_SANITIZED; - } - - /** is this a wildcard of an exact match */ - public boolean isExact() { - return flags == 0; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + flags; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Wildcards other = (Wildcards) obj; - if (flags != other.flags) - return false; - return true; - } - - private final static Joiner pipeJoiner = Joiner.on("|"); - - @Override - public String toString() { - List<String> res = new ArrayList<String>(); - for (Wildcards.Flag flag : Flag.values()) { - if (flag.isFullyOn(flags)) { - res.add(flag.name().toLowerCase()); - } - } - - if (Flag.NW_SRC.isPartiallyOn(flags)) { - res.add("nw_src(/" + getNwSrcMask() + ")"); - } - - if (Flag.NW_DST.isPartiallyOn(flags)) { - res.add("nw_dst(/" + getNwDstMask() + ")"); - } - - return pipeJoiner.join(res); - } - - private final static Joiner commaJoiner = Joiner.on(", "); - - /** a Java expression that constructs 'this' wildcards set */ - public String toJava() { - if(isFull()) { - return "Wildcards.FULL"; - } else if (isExact()){ - return "Wildcards.EXACT"; - } - - StringBuilder b = new StringBuilder(); - - EnumSet<Flag> myFlags = getWildcardedFlags(); - if (myFlags.size() < 3) { - // default to start with empty - b.append("Wildcards.of(" - + commaJoiner.join(prefix("Flag.", myFlags.iterator())) + ")"); - } else { - // too many - start with full - - EnumSet<Flag> invFlags = inverted().getWildcardedFlags(); - b.append("Wildcards.ofMatches(" - + commaJoiner.join(prefix("Flag.", invFlags.iterator())) + ")"); - } - if (Flag.NW_SRC.isPartiallyOn(flags)) { - b.append(".setNwSrcMask(" + getNwSrcMask() + ")"); - } - if (Flag.NW_DST.isPartiallyOn(flags)) { - b.append(".setNwDstMask(" + getNwDstMask() + ")"); - } - return b.toString(); - } - - private Iterator<String> prefix(final String prefix, final Iterator<?> i) { - return new Iterator<String>() { - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public String next() { - Object next = i.next(); - return next == null ? null : prefix + next.toString(); - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFAction.java b/src/main/java/org/openflow/protocol/action/OFAction.java deleted file mode 100644 index 57b5dc1efe690532e373d7663cfd6bcb4b5dcff9..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFAction.java +++ /dev/null @@ -1,173 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.U16; - -/** - * The base class for all OpenFlow Actions. - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public class OFAction implements Cloneable { - /** - * Note the true minimum length for this header is 8 including a pad to 64 - * bit alignment, however as this base class is used for demuxing an - * incoming Action, it is only necessary to read the first 4 bytes. All - * Actions extending this class are responsible for reading/writing the - * first 8 bytes, including the pad if necessary. - */ - public static int MINIMUM_LENGTH = 4; - public static int OFFSET_LENGTH = 2; - public static int OFFSET_TYPE = 0; - - protected OFActionType type; - protected short length; - - /** - * Get the length of this message - * - * @return - */ - public short getLength() { - return length; - } - - /** - * Get the length of this message, unsigned - * - * @return - */ - public int getLengthU() { - return U16.f(length); - } - - /** - * Set the length of this message - * - * @param length - */ - public OFAction setLength(short length) { - this.length = length; - return this; - } - - /** - * Get the type of this message - * - * @return OFActionType enum - */ - public OFActionType getType() { - return this.type; - } - - /** - * Set the type of this message - * - * @param type - */ - public void setType(OFActionType type) { - this.type = type; - } - - /** - * Returns a summary of the message - * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid" - */ - public String toString() { - return "ofaction" + - ";t=" + this.getType() + - ";l=" + this.getLength(); - } - - /** - * Given the output from toString(), - * create a new OFAction - * @param val - * @return - */ - public static OFAction fromString(String val) { - String tokens[] = val.split(";"); - if (!tokens[0].equals("ofaction")) - throw new IllegalArgumentException("expected 'ofaction' but got '" + - tokens[0] + "'"); - String type_tokens[] = tokens[1].split("="); - String len_tokens[] = tokens[2].split("="); - OFAction action = new OFAction(); - action.setLength(Short.valueOf(len_tokens[1])); - action.setType(OFActionType.valueOf(type_tokens[1])); - return action; - } - - public void readFrom(ChannelBuffer data) { - this.type = OFActionType.valueOf(data.readShort()); - this.length = data.readShort(); - // Note missing PAD, see MINIMUM_LENGTH comment for details - } - - public void writeTo(ChannelBuffer data) { - data.writeShort(type.getTypeValue()); - data.writeShort(length); - // Note missing PAD, see MINIMUM_LENGTH comment for details - } - - @Override - public int hashCode() { - final int prime = 347; - int result = 1; - result = prime * result + length; - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFAction)) { - return false; - } - OFAction other = (OFAction) obj; - if (length != other.length) { - return false; - } - if (type == null) { - if (other.type != null) { - return false; - } - } else if (!type.equals(other.type)) { - return false; - } - return true; - } - - /* (non-Javadoc) - * @see java.lang.Object#clone() - */ - @Override - public OFAction clone() throws CloneNotSupportedException { - return (OFAction) super.clone(); - } - -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java b/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java deleted file mode 100644 index 644dc5f2fb53d020f8d8c002d83e0df6e017b8bd..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java +++ /dev/null @@ -1,109 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - -import java.util.Arrays; - -import net.floodlightcontroller.core.web.serializers.ByteArrayMACSerializer; -import net.floodlightcontroller.util.MACAddress; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFPhysicalPort; - -/** - * Represents an ofp_action_dl_addr - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public abstract class OFActionDataLayer extends OFAction { - public static int MINIMUM_LENGTH = 16; - - protected byte[] dataLayerAddress; - - /** - * @return the dataLayerAddress - */ - @JsonSerialize(using=ByteArrayMACSerializer.class) - public byte[] getDataLayerAddress() { - return dataLayerAddress; - } - - /** - * @param dataLayerAddress the dataLayerAddress to set - */ - public void setDataLayerAddress(byte[] dataLayerAddress) { - this.dataLayerAddress = dataLayerAddress; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - if (this.dataLayerAddress == null) - this.dataLayerAddress = new byte[OFPhysicalPort.OFP_ETH_ALEN]; - data.readBytes(this.dataLayerAddress); - data.readInt(); - data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeBytes(this.dataLayerAddress); - data.writeInt(0); - data.writeShort((short) 0); - } - - @Override - public int hashCode() { - final int prime = 347; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(dataLayerAddress); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionDataLayer)) { - return false; - } - OFActionDataLayer other = (OFActionDataLayer) obj; - if (!Arrays.equals(dataLayerAddress, other.dataLayerAddress)) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - builder.append("["); - builder.append(MACAddress.valueOf(dataLayerAddress).toString()); - builder.append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java b/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java deleted file mode 100644 index 48b8d0f84c4f0a7247d6949d8623cca45181692b..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFActionDataLayerDestination extends OFActionDataLayer { - public OFActionDataLayerDestination() { - super(); - super.setType(OFActionType.SET_DL_DST); - super.setLength((short) OFActionDataLayer.MINIMUM_LENGTH); - } - - public OFActionDataLayerDestination(byte[] address) { - this(); - this.dataLayerAddress = address; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java b/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java deleted file mode 100644 index e04561ceefdfb052386b8cf0040b90f84ec2a2ef..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFActionDataLayerSource extends OFActionDataLayer { - public OFActionDataLayerSource() { - super(); - super.setType(OFActionType.SET_DL_SRC); - super.setLength((short) OFActionDataLayer.MINIMUM_LENGTH); - } - - public OFActionDataLayerSource(byte[] address) { - this(); - this.dataLayerAddress = address; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java b/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java deleted file mode 100644 index 537716612ab86bd06e513dfd5f7217fd802ad60e..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java +++ /dev/null @@ -1,136 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_action_enqueue - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public class OFActionEnqueue extends OFAction { - public static int MINIMUM_LENGTH = 16; - - protected short port; - protected int queueId; - - public OFActionEnqueue() { - super.setType(OFActionType.OPAQUE_ENQUEUE); - super.setLength((short) MINIMUM_LENGTH); - } - - public OFActionEnqueue(short port, int queueId) { - this(); - this.port = port; - this.queueId = queueId; - } - - /** - * Get the output port - * @return - */ - public short getPort() { - return this.port; - } - - /** - * Set the output port - * @param port - */ - public void setPort(short port) { - this.port = port; - } - - /** - * @return the queueId - */ - public int getQueueId() { - return queueId; - } - - /** - * @param queueId the queueId to set - */ - public void setQueueId(int queueId) { - this.queueId = queueId; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.port = data.readShort(); - data.readShort(); - data.readInt(); - this.queueId = data.readInt(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.port); - data.writeShort((short) 0); - data.writeInt(0); - data.writeInt(this.queueId); - } - - @Override - public int hashCode() { - final int prime = 349; - int result = super.hashCode(); - result = prime * result + port; - result = prime * result + queueId; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionEnqueue)) { - return false; - } - OFActionEnqueue other = (OFActionEnqueue) obj; - if (port != other.port) { - return false; - } - if (queueId != other.queueId) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - builder.append("["); - builder.append("Port: "); - builder.append(port); - builder.append(", Queue Id: "); - builder.append(queueId); - builder.append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java deleted file mode 100644 index 67bc5a82203fe5d821aabb19a2d352b6df0eabc6..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java +++ /dev/null @@ -1,98 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - - -import net.floodlightcontroller.packet.IPv4; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_action_nw_addr - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public abstract class OFActionNetworkLayerAddress extends OFAction { - public static int MINIMUM_LENGTH = 8; - - protected int networkAddress; - - /** - * @return the networkAddress - */ - public int getNetworkAddress() { - return networkAddress; - } - - /** - * @param networkAddress the networkAddress to set - */ - public void setNetworkAddress(int networkAddress) { - this.networkAddress = networkAddress; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.networkAddress = data.readInt(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeInt(this.networkAddress); - } - - @Override - public int hashCode() { - final int prime = 353; - int result = super.hashCode(); - result = prime * result + networkAddress; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionNetworkLayerAddress)) { - return false; - } - OFActionNetworkLayerAddress other = (OFActionNetworkLayerAddress) obj; - if (networkAddress != other.networkAddress) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - builder.append("["); - builder.append(IPv4.fromIPv4Address(networkAddress)); - builder.append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java deleted file mode 100644 index 13c14ff0bfb9435c5c8e9156344583e575c04624..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFActionNetworkLayerDestination extends OFActionNetworkLayerAddress { - public OFActionNetworkLayerDestination() { - super(); - super.setType(OFActionType.SET_NW_DST); - super.setLength((short) OFActionNetworkLayerAddress.MINIMUM_LENGTH); - } - - public OFActionNetworkLayerDestination(int ip) { - this(); - this.networkAddress = ip; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java deleted file mode 100644 index ef1d005e32f1f5b6aa92945a52f50df236413f74..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFActionNetworkLayerSource extends OFActionNetworkLayerAddress { - public OFActionNetworkLayerSource() { - super(); - super.setType(OFActionType.SET_NW_SRC); - super.setLength((short) OFActionNetworkLayerAddress.MINIMUM_LENGTH); - } - - public OFActionNetworkLayerSource(int ip) { - this(); - this.networkAddress = ip; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java deleted file mode 100644 index ec91c764916beff70ee7bec9e8ba4e7a27f08645..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java +++ /dev/null @@ -1,110 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_action_enqueue - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public class OFActionNetworkTypeOfService extends OFAction { - public static int MINIMUM_LENGTH = 8; - - protected byte networkTypeOfService; - - public OFActionNetworkTypeOfService() { - super.setType(OFActionType.SET_NW_TOS); - super.setLength((short) MINIMUM_LENGTH); - } - - public OFActionNetworkTypeOfService(byte tos) { - this(); - this.networkTypeOfService = tos; - } - - - /** - * @return the networkTypeOfService - */ - public byte getNetworkTypeOfService() { - return networkTypeOfService; - } - - /** - * @param networkTypeOfService the networkTypeOfService to set - */ - public void setNetworkTypeOfService(byte networkTypeOfService) { - this.networkTypeOfService = networkTypeOfService; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.networkTypeOfService = data.readByte(); - data.readShort(); - data.readByte(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeByte(this.networkTypeOfService); - data.writeShort((short) 0); - data.writeByte((byte) 0); - } - - @Override - public int hashCode() { - final int prime = 359; - int result = super.hashCode(); - result = prime * result + networkTypeOfService; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionNetworkTypeOfService)) { - return false; - } - OFActionNetworkTypeOfService other = (OFActionNetworkTypeOfService) obj; - if (networkTypeOfService != other.networkTypeOfService) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - builder.append("["); - builder.append(networkTypeOfService); - builder.append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionOutput.java b/src/main/java/org/openflow/protocol/action/OFActionOutput.java deleted file mode 100644 index beca7e4f21f84a146f2b01a0a5585527c8fc67ef..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionOutput.java +++ /dev/null @@ -1,161 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - * @author Rob Sherwood (rob.sherwood@stanford.edu) - */ -public class OFActionOutput extends OFAction implements Cloneable { - public static int MINIMUM_LENGTH = 8; - - protected short port; - protected short maxLength; - - public OFActionOutput() { - super.setType(OFActionType.OUTPUT); - super.setLength((short) MINIMUM_LENGTH); - } - - /** - * Create an Output Action sending packets out the specified - * OpenFlow port. - * - * This is the most common creation pattern for OFActions. - * - * @param port - */ - - public OFActionOutput(short port) { - this(port, (short) 65535); - } - - /** - * Create an Output Action specifying both the port AND - * the snaplen of the packet to send out that port. - * The length field is only meaningful when port == OFPort.OFPP_CONTROLLER - * @param port - * @param maxLength The maximum number of bytes of the packet to send. - * Most hardware only supports this value for OFPP_CONTROLLER - */ - - public OFActionOutput(short port, short maxLength) { - super(); - super.setType(OFActionType.OUTPUT); - super.setLength((short) MINIMUM_LENGTH); - this.port = port; - this.maxLength = maxLength; - } - - /** - * Get the output port - * @return - */ - public short getPort() { - return this.port; - } - - /** - * Set the output port - * @param port - */ - public OFActionOutput setPort(short port) { - this.port = port; - return this; - } - - /** - * Get the max length to send to the controller - * @return - */ - public short getMaxLength() { - return this.maxLength; - } - - /** - * Set the max length to send to the controller - * @param maxLength - */ - public OFActionOutput setMaxLength(short maxLength) { - this.maxLength = maxLength; - return this; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.port = data.readShort(); - this.maxLength = data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(port); - data.writeShort(maxLength); - } - - @Override - public int hashCode() { - final int prime = 367; - int result = super.hashCode(); - result = prime * result + maxLength; - result = prime * result + port; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionOutput)) { - return false; - } - OFActionOutput other = (OFActionOutput) obj; - if (maxLength != other.maxLength) { - return false; - } - if (port != other.port) { - return false; - } - return true; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - builder.append("["); - builder.append(port); - builder.append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java b/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java deleted file mode 100644 index f79c84d391751abeb8e49606382a9e1325264f39..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java +++ /dev/null @@ -1,60 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; - - -/** - * Represents an ofp_action_strip_vlan - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public class OFActionStripVirtualLan extends OFAction { - public static int MINIMUM_LENGTH = 8; - - public OFActionStripVirtualLan() { - super(); - super.setType(OFActionType.STRIP_VLAN); - super.setLength((short) MINIMUM_LENGTH); - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - // PAD - data.readInt(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - // PAD - data.writeInt(0); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java b/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java deleted file mode 100644 index 696c1c7a29d01132c2667e0cda9639b3dcc4eec9..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java +++ /dev/null @@ -1,98 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_action_tp_port - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public abstract class OFActionTransportLayer extends OFAction { - public static int MINIMUM_LENGTH = 8; - - protected short transportPort; - - /** - * @return the transportPort - */ - public short getTransportPort() { - return transportPort; - } - - /** - * @param transportPort the transportPort to set - */ - public void setTransportPort(short transportPort) { - this.transportPort = transportPort; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.transportPort = data.readShort(); - data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.transportPort); - data.writeShort((short) 0); - } - - @Override - public int hashCode() { - final int prime = 373; - int result = super.hashCode(); - result = prime * result + transportPort; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionTransportLayer)) { - return false; - } - OFActionTransportLayer other = (OFActionTransportLayer) obj; - if (transportPort != other.transportPort) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append(type); - builder.append("["); - builder.append(transportPort); - builder.append("]"); - return builder.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java b/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java deleted file mode 100644 index 7e7b0f1fc6539d306ed69548e1b24c33a0aa2d65..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFActionTransportLayerDestination extends OFActionTransportLayer { - public OFActionTransportLayerDestination() { - super(); - super.setType(OFActionType.SET_TP_DST); - super.setLength((short) OFActionTransportLayer.MINIMUM_LENGTH); - } - - public OFActionTransportLayerDestination(short port) { - this(); - this.transportPort = port; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java b/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java deleted file mode 100644 index 385aa53c88478f04f92644271342ee02c6e93d25..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFActionTransportLayerSource extends OFActionTransportLayer { - public OFActionTransportLayerSource() { - super(); - super.setType(OFActionType.SET_TP_SRC); - super.setLength((short) OFActionTransportLayer.MINIMUM_LENGTH); - } - - public OFActionTransportLayerSource(short port) { - this(); - this.transportPort = port; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionType.java b/src/main/java/org/openflow/protocol/action/OFActionType.java deleted file mode 100644 index 18229170b77dc1a01984cfc9f156272f5ad858c5..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionType.java +++ /dev/null @@ -1,203 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - -import java.lang.reflect.Constructor; - -import org.openflow.protocol.Instantiable; - -/** - * List of OpenFlow Action types and mappings to wire protocol value and - * derived classes - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public enum OFActionType { - OUTPUT (0, OFActionOutput.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionOutput(); - }}), - SET_VLAN_ID (1, OFActionVirtualLanIdentifier.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionVirtualLanIdentifier(); - }}), - SET_VLAN_PCP (2, OFActionVirtualLanPriorityCodePoint.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionVirtualLanPriorityCodePoint(); - }}), - STRIP_VLAN (3, OFActionStripVirtualLan.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionStripVirtualLan(); - }}), - SET_DL_SRC (4, OFActionDataLayerSource.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionDataLayerSource(); - }}), - SET_DL_DST (5, OFActionDataLayerDestination.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionDataLayerDestination(); - }}), - SET_NW_SRC (6, OFActionNetworkLayerSource.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionNetworkLayerSource(); - }}), - SET_NW_DST (7, OFActionNetworkLayerDestination.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionNetworkLayerDestination(); - }}), - SET_NW_TOS (8, OFActionNetworkTypeOfService.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionNetworkTypeOfService(); - }}), - SET_TP_SRC (9, OFActionTransportLayerSource.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionTransportLayerSource(); - }}), - SET_TP_DST (10, OFActionTransportLayerDestination.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionTransportLayerDestination(); - }}), - OPAQUE_ENQUEUE (11, OFActionEnqueue.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionEnqueue(); - }}), - VENDOR (0xffff, OFActionVendor.class, new Instantiable<OFAction>() { - @Override - public OFAction instantiate() { - return new OFActionVendorGeneric(); - }}); - - protected static OFActionType[] mapping; - - protected Class<? extends OFAction> clazz; - protected Constructor<? extends OFAction> constructor; - protected Instantiable<OFAction> instantiable; - protected int minLen; - protected short type; - - /** - * Store some information about the OpenFlow Action type, including wire - * protocol type number, length, and derrived class - * - * @param type Wire protocol number associated with this OFType - * @param clazz The Java class corresponding to this type of OpenFlow Action - * @param instantiable the instantiable for the OFAction this type represents - */ - OFActionType(int type, Class<? extends OFAction> clazz, Instantiable<OFAction> instantiable) { - this.type = (short) type; - this.clazz = clazz; - this.instantiable = instantiable; - try { - this.constructor = clazz.getConstructor(new Class[]{}); - } catch (Exception e) { - throw new RuntimeException( - "Failure getting constructor for class: " + clazz, e); - } - OFActionType.addMapping(this.type, this); - } - - /** - * Adds a mapping from type value to OFActionType enum - * - * @param i OpenFlow wire protocol Action type value - * @param t type - */ - static public void addMapping(short i, OFActionType t) { - if (mapping == null) - mapping = new OFActionType[16]; - // bring higher mappings down to the edge of our array - if (i < 0) - i = (short) (16 + i); - OFActionType.mapping[i] = t; - } - - /** - * Given a wire protocol OpenFlow type number, return the OFType associated - * with it - * - * @param i wire protocol number - * @return OFType enum type - */ - - static public OFActionType valueOf(short i) { - if (i < 0) - i = (short) (16+i); - return OFActionType.mapping[i]; - } - - /** - * @return Returns the wire protocol value corresponding to this - * OFActionType - */ - public short getTypeValue() { - return this.type; - } - - /** - * @return return the OFAction subclass corresponding to this OFActionType - */ - public Class<? extends OFAction> toClass() { - return clazz; - } - - /** - * Returns the no-argument Constructor of the implementation class for - * this OFActionType - * @return the constructor - */ - public Constructor<? extends OFAction> getConstructor() { - return constructor; - } - - /** - * Returns a new instance of the OFAction represented by this OFActionType - * @return the new object - */ - public OFAction newInstance() { - return instantiable.instantiate(); - } - - /** - * @return the instantiable - */ - public Instantiable<OFAction> getInstantiable() { - return instantiable; - } - - /** - * @param instantiable the instantiable to set - */ - public void setInstantiable(Instantiable<OFAction> instantiable) { - this.instantiable = instantiable; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionVendor.java b/src/main/java/org/openflow/protocol/action/OFActionVendor.java deleted file mode 100644 index 5860ef1160ae43fe3606a582c8e7d7ae842820eb..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionVendor.java +++ /dev/null @@ -1,94 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public abstract class OFActionVendor extends OFAction { - public static int MINIMUM_LENGTH = 8; - - protected int vendor; - - public OFActionVendor() { - super(); - super.setType(OFActionType.VENDOR); - super.setLength((short) MINIMUM_LENGTH); - } - - /** - * @return the vendor - */ - public int getVendor() { - return vendor; - } - - /** - * @param vendor the vendor to set - */ - public void setVendor(int vendor) { - this.vendor = vendor; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.vendor = data.readInt(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeInt(this.vendor); - } - - @Override - public int hashCode() { - final int prime = 379; - int result = super.hashCode(); - result = prime * result + vendor; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionVendor)) { - return false; - } - OFActionVendor other = (OFActionVendor) obj; - if (vendor != other.vendor) { - return false; - } - return true; - } - - @Override - public String toString() { - return super.toString() + "; vendor=" + vendor; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java b/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java deleted file mode 100644 index 4f7859f5ec43e8e13ff8340c50f5cda6f2d2311c..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java +++ /dev/null @@ -1,96 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.action; - - -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** A generic / unparsed vendor action. This action is returned by - * BasicFactory.readFromWire if no more specific OFVendorActionFactory - * is registered. - * - * @author David Erickson (daviderickson@cs.stanford.edu) - * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> - */ -public class OFActionVendorGeneric extends OFActionVendor { - public static int MINIMUM_LENGTH = 8; - - private final static byte[] EMPTY_ARRAY = new byte[0]; - - protected byte[] vendorData; - - public OFActionVendorGeneric() { - super(); - } - - public byte[] getVendorData() { - return vendorData; - } - - public void setVendorData(byte[] vendorData) { - this.vendorData = vendorData; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - - int vendorDataLength = this.getLength() - MINIMUM_LENGTH; - if (vendorDataLength > 0) { - vendorData = new byte[vendorDataLength]; - data.readBytes(vendorData); - } else { - vendorData = EMPTY_ARRAY; - } - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeInt(this.vendor); - data.writeBytes(vendorData); - } - - @Override - public int hashCode() { - final int prime = 379; - int result = super.hashCode(); - result = prime * result + Arrays.hashCode(vendorData); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionVendorGeneric)) { - return false; - } - OFActionVendorGeneric other = (OFActionVendorGeneric) obj; - if (!Arrays.equals(vendorData, other.vendorData)) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java b/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java deleted file mode 100644 index 5bd0e0bda156cc34ac915ee29900e8a83b5cfbd0..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java +++ /dev/null @@ -1,98 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_action_vlan_vid - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public class OFActionVirtualLanIdentifier extends OFAction { - public static int MINIMUM_LENGTH = 8; - - protected short virtualLanIdentifier; - - public OFActionVirtualLanIdentifier() { - super.setType(OFActionType.SET_VLAN_ID); - super.setLength((short) MINIMUM_LENGTH); - } - - public OFActionVirtualLanIdentifier(short vlanId) { - this(); - this.virtualLanIdentifier = vlanId; - } - - /** - * @return the virtualLanIdentifier - */ - public short getVirtualLanIdentifier() { - return virtualLanIdentifier; - } - - /** - * @param virtualLanIdentifier the virtualLanIdentifier to set - */ - public void setVirtualLanIdentifier(short virtualLanIdentifier) { - this.virtualLanIdentifier = virtualLanIdentifier; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.virtualLanIdentifier = data.readShort(); - data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.virtualLanIdentifier); - data.writeShort((short) 0); - } - - @Override - public int hashCode() { - final int prime = 383; - int result = super.hashCode(); - result = prime * result + virtualLanIdentifier; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionVirtualLanIdentifier)) { - return false; - } - OFActionVirtualLanIdentifier other = (OFActionVirtualLanIdentifier) obj; - if (virtualLanIdentifier != other.virtualLanIdentifier) { - return false; - } - return true; - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java b/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java deleted file mode 100644 index 9202df33f82548c74919d7b34be5714aa9036256..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java +++ /dev/null @@ -1,100 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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. -**/ - -/** - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -package org.openflow.protocol.action; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_action_vlan_pcp - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public class OFActionVirtualLanPriorityCodePoint extends OFAction { - public static int MINIMUM_LENGTH = 8; - - protected byte virtualLanPriorityCodePoint; - - public OFActionVirtualLanPriorityCodePoint() { - super.setType(OFActionType.SET_VLAN_PCP); - super.setLength((short) MINIMUM_LENGTH); - } - - public OFActionVirtualLanPriorityCodePoint(byte priority) { - this(); - this.virtualLanPriorityCodePoint = priority; - } - - /** - * @return the virtualLanPriorityCodePoint - */ - public byte getVirtualLanPriorityCodePoint() { - return virtualLanPriorityCodePoint; - } - - /** - * @param virtualLanPriorityCodePoint the virtualLanPriorityCodePoint to set - */ - public void setVirtualLanPriorityCodePoint(byte virtualLanPriorityCodePoint) { - this.virtualLanPriorityCodePoint = virtualLanPriorityCodePoint; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - this.virtualLanPriorityCodePoint = data.readByte(); - data.readShort(); // pad - data.readByte(); // pad - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeByte(this.virtualLanPriorityCodePoint); - data.writeShort((short) 0); - data.writeByte((byte) 0); - } - - @Override - public int hashCode() { - final int prime = 389; - int result = super.hashCode(); - result = prime * result + virtualLanPriorityCodePoint; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (!(obj instanceof OFActionVirtualLanPriorityCodePoint)) { - return false; - } - OFActionVirtualLanPriorityCodePoint other = (OFActionVirtualLanPriorityCodePoint) obj; - if (virtualLanPriorityCodePoint != other.virtualLanPriorityCodePoint) { - return false; - } - return true; - } -} \ No newline at end of file diff --git a/src/main/java/org/openflow/protocol/factory/BasicFactory.java b/src/main/java/org/openflow/protocol/factory/BasicFactory.java deleted file mode 100644 index f484a167f5cd64f1eaec92dd366a4f0ff02a8ece..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/BasicFactory.java +++ /dev/null @@ -1,346 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -import java.util.ArrayList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionType; -import org.openflow.protocol.action.OFActionVendor; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.protocol.statistics.OFVendorStatistics; -import org.openflow.protocol.vendor.OFByteArrayVendorData; -import org.openflow.protocol.vendor.OFVendorData; -import org.openflow.protocol.vendor.OFVendorDataType; -import org.openflow.protocol.vendor.OFVendorId; - - -/** - * A basic OpenFlow factory that supports naive creation of both Messages and - * Actions. - * - * @author David Erickson (daviderickson@cs.stanford.edu) - * @author Rob Sherwood (rob.sherwood@stanford.edu) - * - */ -public enum BasicFactory implements OFMessageFactory, OFActionFactory, - OFStatisticsFactory, OFVendorDataFactory { - SINGLETON_INSTANCE; - - - private final OFVendorActionRegistry vendorActionRegistry; - - private BasicFactory() { - vendorActionRegistry = OFVendorActionRegistry.getInstance(); - } - - public static BasicFactory getInstance() { - return SINGLETON_INSTANCE; - } - - /** - * create and return a new instance of a message for OFType t. Also injects - * factories for those message types that implement the *FactoryAware - * interfaces. - * - * @return a newly created instance that may be modified / used freely by - * the caller - */ - @Override - public OFMessage getMessage(OFType t) { - OFMessage message = t.newInstance(); - injectFactories(message); - return message; - } - - @Override - public List<OFMessage> parseMessage(ChannelBuffer data) throws MessageParseException { - List<OFMessage> msglist = new ArrayList<OFMessage>(); - OFMessage msg = null; - - while (data.readableBytes() >= OFMessage.MINIMUM_LENGTH) { - data.markReaderIndex(); - msg = this.parseMessageOne(data); - if (msg == null) { - data.resetReaderIndex(); - break; - } - else { - msglist.add(msg); - } - } - - if (msglist.size() == 0) { - return null; - } - return msglist; - - } - - public OFMessage parseMessageOne(ChannelBuffer data) throws MessageParseException { - try { - OFMessage demux = new OFMessage(); - OFMessage ofm = null; - - if (data.readableBytes() < OFMessage.MINIMUM_LENGTH) - return ofm; - - data.markReaderIndex(); - demux.readFrom(data); - data.resetReaderIndex(); - - if (demux.getLengthU() > data.readableBytes()) - return ofm; - - ofm = getMessage(demux.getType()); - if (ofm == null) - return null; - - injectFactories(ofm); - ofm.readFrom(data); - if (OFMessage.class.equals(ofm.getClass())) { - // advance the position for un-implemented messages - data.readerIndex(data.readerIndex()+(ofm.getLengthU() - - OFMessage.MINIMUM_LENGTH)); - } - - return ofm; - } catch (Exception e) { - /* Write the offending data along with the error message */ - data.resetReaderIndex(); - String msg = - "Message Parse Error for packet:" + dumpBuffer(data) + - "\nException: " + e.toString(); - data.resetReaderIndex(); - - throw new MessageParseException(msg, e); - } - } - - private void injectFactories(OFMessage ofm) { - if (ofm instanceof OFActionFactoryAware) { - ((OFActionFactoryAware)ofm).setActionFactory(this); - } - if (ofm instanceof OFMessageFactoryAware) { - ((OFMessageFactoryAware)ofm).setMessageFactory(this); - } - if (ofm instanceof OFStatisticsFactoryAware) { - ((OFStatisticsFactoryAware)ofm).setStatisticsFactory(this); - } - if (ofm instanceof OFVendorDataFactoryAware) { - ((OFVendorDataFactoryAware)ofm).setVendorDataFactory(this); - } - } - - @Override - public OFAction getAction(OFActionType t) { - return t.newInstance(); - } - - @Override - public List<OFAction> parseActions(ChannelBuffer data, int length) { - return parseActions(data, length, 0); - } - - @Override - public List<OFAction> parseActions(ChannelBuffer data, int length, int limit) { - List<OFAction> results = new ArrayList<OFAction>(); - OFAction demux = new OFAction(); - OFAction ofa; - int end = data.readerIndex() + length; - - while (limit == 0 || results.size() <= limit) { - if ((data.readableBytes() < OFAction.MINIMUM_LENGTH || - (data.readerIndex() + OFAction.MINIMUM_LENGTH) > end)) - return results; - - data.markReaderIndex(); - demux.readFrom(data); - data.resetReaderIndex(); - - if ((demux.getLengthU() > data.readableBytes() || - (data.readerIndex() + demux.getLengthU()) > end)) - return results; - - ofa = parseActionOne(demux.getType(), data); - results.add(ofa); - } - - return results; - } - - private OFAction parseActionOne(OFActionType type, ChannelBuffer data) { - OFAction ofa; - data.markReaderIndex(); - ofa = getAction(type); - ofa.readFrom(data); - - if(type == OFActionType.VENDOR) { - OFActionVendor vendorAction = (OFActionVendor) ofa; - - OFVendorActionFactory vendorActionFactory = vendorActionRegistry.get(vendorAction.getVendor()); - - if(vendorActionFactory != null) { - // if we have a specific vendorActionFactory for this vendor id, - // delegate to it for vendor-specific reparsing of the message - data.resetReaderIndex(); - OFActionVendor newAction = vendorActionFactory.readFrom(data); - if(newAction != null) - ofa = newAction; - } - } - - if (OFAction.class.equals(ofa.getClass())) { - // advance the position for un-implemented messages - data.readerIndex(data.readerIndex()+(ofa.getLengthU() - - OFAction.MINIMUM_LENGTH)); - } - return ofa; - } - - @Override - public OFActionFactory getActionFactory() { - return this; - } - - @Override - public OFStatistics getStatistics(OFType t, OFStatisticsType st) { - return st.newInstance(t); - } - - @Override - public List<OFStatistics> parseStatistics(OFType t, OFStatisticsType st, - ChannelBuffer data, int length) { - return parseStatistics(t, st, data, length, 0); - } - - /** - * @param t - * OFMessage type: should be one of stats_request or stats_reply - * @param st - * statistics type of this message, e.g., DESC, TABLE - * @param data - * buffer to read from - * @param length - * length of statistics - * @param limit - * number of statistics to grab; 0 == all - * - * @return list of statistics - */ - - @Override - public List<OFStatistics> parseStatistics(OFType t, OFStatisticsType st, - ChannelBuffer data, int length, int limit) { - List<OFStatistics> results = new ArrayList<OFStatistics>(); - OFStatistics statistics = getStatistics(t, st); - - int start = data.readerIndex(); - int count = 0; - - while (limit == 0 || results.size() <= limit) { - // TODO Create a separate MUX/DEMUX path for vendor stats - if (statistics instanceof OFVendorStatistics) - ((OFVendorStatistics)statistics).setLength(length); - - /** - * can't use data.remaining() here, b/c there could be other data - * buffered past this message - */ - if ((length - count) >= statistics.getLength()) { - if (statistics instanceof OFActionFactoryAware) - ((OFActionFactoryAware)statistics).setActionFactory(this); - statistics.readFrom(data); - results.add(statistics); - count += statistics.getLength(); - statistics = getStatistics(t, st); - } else { - if (count < length) { - /** - * Nasty case: partial/incomplete statistic found even - * though we have a full message. Found when NOX sent - * agg_stats request with wrong agg statistics length (52 - * instead of 56) - * - * just throw the rest away, or we will break framing - */ - data.readerIndex(start + length); - } - return results; - } - } - return results; // empty; no statistics at all - } - - - @Override - public OFVendorData getVendorData(OFVendorId vendorId, - OFVendorDataType vendorDataType) { - if (vendorDataType == null) - return null; - - return vendorDataType.newInstance(); - } - - /** - * Attempts to parse and return the OFVendorData contained in the given - * ChannelBuffer, beginning right after the vendor id. - * @param vendor the vendor id that was parsed from the OFVendor message. - * @param data the ChannelBuffer from which to parse the vendor data - * @param length the length to the end of the enclosing message. - * @return an OFVendorData instance - */ - @Override - public OFVendorData parseVendorData(int vendor, ChannelBuffer data, - int length) { - OFVendorDataType vendorDataType = null; - OFVendorId vendorId = OFVendorId.lookupVendorId(vendor); - if (vendorId != null) { - data.markReaderIndex(); - vendorDataType = vendorId.parseVendorDataType(data, length); - data.resetReaderIndex(); - } - - OFVendorData vendorData = getVendorData(vendorId, vendorDataType); - if (vendorData == null) - vendorData = new OFByteArrayVendorData(); - - vendorData.readFrom(data, length); - - return vendorData; - } - - public static String dumpBuffer(ChannelBuffer data) { - // NOTE: Reads all the bytes in buffer from current read offset. - // Set/Reset ReaderIndex if you want to read from a different location - int len = data.readableBytes(); - StringBuffer sb = new StringBuffer(); - for (int i=0 ; i<len; i++) { - if (i%32 == 0) sb.append("\n"); - if (i%4 == 0) sb.append(" "); - sb.append(String.format("%02x", data.getUnsignedByte(i))); - } - return sb.toString(); - } - -} diff --git a/src/main/java/org/openflow/protocol/factory/MessageParseException.java b/src/main/java/org/openflow/protocol/factory/MessageParseException.java deleted file mode 100644 index 20f381ef8d095a22f98936640435b94a61f5c237..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/MessageParseException.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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 org.openflow.protocol.factory; - -/** - * Exception thrown when an openflow message fails to parse properly - */ -public class MessageParseException extends Exception { - /** - * - */ - private static final long serialVersionUID = -75893812926304726L; - - public MessageParseException() { - super(); - } - - public MessageParseException(String message, Throwable cause) { - super(message, cause); - this.setStackTrace(cause.getStackTrace()); - } - - public MessageParseException(String message) { - super(message); - } - - public MessageParseException(Throwable cause) { - super(cause); - this.setStackTrace(cause.getStackTrace()); - } -} diff --git a/src/main/java/org/openflow/protocol/factory/OFActionFactory.java b/src/main/java/org/openflow/protocol/factory/OFActionFactory.java deleted file mode 100644 index c3cd06265bf9a7d0b832afabc5ff18ce0412eacb..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFActionFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionType; - - -/** - * The interface to factories used for retrieving OFAction instances. All - * methods are expected to be thread-safe. - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface OFActionFactory { - /** - * Retrieves an OFAction instance corresponding to the specified - * OFActionType - * @param t the type of the OFAction to be retrieved - * @return an OFAction instance - */ - public OFAction getAction(OFActionType t); - - /** - * Attempts to parse and return all OFActions contained in the given - * ByteBuffer, beginning at the ByteBuffer's position, and ending at - * position+length. - * @param data the ChannelBuffer to parse for OpenFlow actions - * @param length the number of Bytes to examine for OpenFlow actions - * @return a list of OFAction instances - */ - public List<OFAction> parseActions(ChannelBuffer data, int length); - - /** - * Attempts to parse and return all OFActions contained in the given - * ByteBuffer, beginning at the ByteBuffer's position, and ending at - * position+length. - * @param data the ChannelBuffer to parse for OpenFlow actions - * @param length the number of Bytes to examine for OpenFlow actions - * @param limit the maximum number of messages to return, 0 means no limit - * @return a list of OFAction instances - */ - public List<OFAction> parseActions(ChannelBuffer data, int length, int limit); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java deleted file mode 100644 index a97a95c0a6c666fc01112cb629ad750c0f4d8012..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java +++ /dev/null @@ -1,31 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -/** - * Objects implementing this interface are expected to be instantiated with an - * instance of an OFActionFactory - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface OFActionFactoryAware { - /** - * Sets the OFActionFactory - * @param actionFactory - */ - public void setActionFactory(OFActionFactory actionFactory); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java b/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java deleted file mode 100644 index 8bb7045463aee7cfc6d66a207f9737b8a7eabdf6..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; - - -/** - * The interface to factories used for retrieving OFMessage instances. All - * methods are expected to be thread-safe. - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface OFMessageFactory { - /** - * Retrieves an OFMessage instance corresponding to the specified OFType - * @param t the type of the OFMessage to be retrieved - * @return an OFMessage instance - */ - public OFMessage getMessage(OFType t); - - /** - * Attempts to parse and return a OFMessages contained in the given - * ChannelBuffer, beginning at the ChannelBuffer's position, and ending at the - * after the first parsed message - * @param data the ChannelBuffer to parse for an OpenFlow message - * @return a list of OFMessage instances - * @throws MessageParseException - */ - public List<OFMessage> parseMessage(ChannelBuffer data) throws MessageParseException; - - /** - * Retrieves an OFActionFactory - * @return an OFActionFactory - */ - public OFActionFactory getActionFactory(); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java deleted file mode 100644 index adb1421e13a7638b84f6aca7c9e320a4dc944e69..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java +++ /dev/null @@ -1,35 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -/** - * @author Rob Sherwood (rob.sherwood@stanford.edu) - * - */ -public interface OFMessageFactoryAware { - - /** - * Sets the message factory for this object - * - * @param factory - */ - void setMessageFactory(OFMessageFactory factory); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java b/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java deleted file mode 100644 index 32eb3cbffa5fb1765439108c4691279981743240..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java +++ /dev/null @@ -1,72 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFType; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; - - -/** - * The interface to factories used for retrieving OFStatistics instances. All - * methods are expected to be thread-safe. - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface OFStatisticsFactory { - /** - * Retrieves an OFStatistics instance corresponding to the specified - * OFStatisticsType - * @param t the type of the containing OFMessage, only accepts statistics - * request or reply - * @param st the type of the OFStatistics to be retrieved - * @return an OFStatistics instance - */ - public OFStatistics getStatistics(OFType t, OFStatisticsType st); - - /** - * Attempts to parse and return all OFStatistics contained in the given - * ByteBuffer, beginning at the ByteBuffer's position, and ending at - * position+length. - * @param t the type of the containing OFMessage, only accepts statistics - * request or reply - * @param st the type of the OFStatistics to be retrieved - * @param data the ChannelBuffer to parse for OpenFlow Statistics - * @param length the number of Bytes to examine for OpenFlow Statistics - * @return a list of OFStatistics instances - */ - public List<OFStatistics> parseStatistics(OFType t, - OFStatisticsType st, ChannelBuffer data, int length); - - /** - * Attempts to parse and return all OFStatistics contained in the given - * ByteBuffer, beginning at the ByteBuffer's position, and ending at - * position+length. - * @param t the type of the containing OFMessage, only accepts statistics - * request or reply - * @param st the type of the OFStatistics to be retrieved - * @param data the ChannelBuffer to parse for OpenFlow Statistics - * @param length the number of Bytes to examine for OpenFlow Statistics - * @param limit the maximum number of messages to return, 0 means no limit - * @return a list of OFStatistics instances - */ - public List<OFStatistics> parseStatistics(OFType t, - OFStatisticsType st, ChannelBuffer data, int length, int limit); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java deleted file mode 100644 index 52ab09a9501ce05e358766d6d08056dd33997b07..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java +++ /dev/null @@ -1,31 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.factory; - -/** - * Objects implementing this interface are expected to be instantiated with an - * instance of an OFStatisticsFactory - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public interface OFStatisticsFactoryAware { - /** - * Sets the OFStatisticsFactory - * @param statisticsFactory - */ - public void setStatisticsFactory(OFStatisticsFactory statisticsFactory); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java b/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java deleted file mode 100644 index eb89810b78b9709b89b651731cd20d5615f6b80e..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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 org.openflow.protocol.factory; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.action.OFActionVendor; - -/** Interface contract for an actionfactory that creates vendor-specific actions. - * VendorActionFactories are registered with the BasicFactory for a specific - * vendor id. - * <p> - * <b>Note:</b> Implementations are expected to be thread-safe. - * - * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> - */ -public interface OFVendorActionFactory { - - /** parse the data from the wire, create and return a vendor-specific action. - * - * @param data contains a serialized vendor action at the current readerPosition. - * The full message is guaranteed to be available in the buffer. - * - * @return upon success returns a newly allocated vendor-specific - * action instance, and advances the readerPosition in data for the - * entire length. Upon failure, returns null and leaves the readerPosition - * in data unmodified. - */ - OFActionVendor readFrom(ChannelBuffer data); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java b/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java deleted file mode 100644 index 1f556812c65bde8dce9e7c17de2ac050a8c24160..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2013, Big Switch Networks, Inc. - * - * 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 org.openflow.protocol.factory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** Singleton registry object that holds a mapping from vendor ids to vendor-specific - * mapping factories. Threadsafe. - * - * @author Andreas Wundsam <andreas.wundsam@bigswitch.com> - */ -public class OFVendorActionRegistry { - private static class InstanceHolder { - private final static OFVendorActionRegistry instance = new OFVendorActionRegistry(); - } - - public static OFVendorActionRegistry getInstance() { - return InstanceHolder.instance; - } - private final Map <Integer, OFVendorActionFactory> vendorActionFactories; - - public OFVendorActionRegistry() { - vendorActionFactories = new ConcurrentHashMap<Integer, OFVendorActionFactory>(); - } - - public OFVendorActionFactory register(int vendorId, OFVendorActionFactory factory) { - return vendorActionFactories.put(vendorId, factory); - } - - public OFVendorActionFactory get(int vendorId) { - return vendorActionFactories.get(vendorId); - } - - -} diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java b/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java deleted file mode 100644 index d754a4a31087cc309cc6ac8885d05c492c0da23a..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java +++ /dev/null @@ -1,69 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.factory; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.vendor.OFVendorData; -import org.openflow.protocol.vendor.OFVendorDataType; -import org.openflow.protocol.vendor.OFVendorId; - -/** - * The interface to factories used for parsing/creating OFVendorData instances. - * All methods are expected to be thread-safe. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public interface OFVendorDataFactory { - /** - * Retrieves an OFVendorData instance corresponding to the specified - * OFVendorId and OFVendorDataType. There are 3 possible cases for - * how this will be called: - * - * 1) If the vendor id in the OFVendor message is an unknown value, - * then this method is called with both vendorId and vendorDataType - * set to null. In this case typically the factory method should - * return an instance of OFGenericVendorData that just contains - * the raw byte array of the vendor data. - * - * 2) If the vendor id is known but no vendor data type has been - * registered for the data in the message, then vendorId is set to - * the appropriate OFVendorId instance and OFVendorDataType is set - * to null. This would typically be handled the same way as #1 - * - * 3) If both the vendor id and and vendor data type are known, then - * typically you'd just call the method in OFVendorDataType to - * instantiate the appropriate subclass of OFVendorData. - * - * @param vendorId the vendorId of the containing OFVendor message - * @param vendorDataType the type of the OFVendorData to be retrieved - * @return an OFVendorData instance - */ - public OFVendorData getVendorData(OFVendorId vendorId, - OFVendorDataType vendorDataType); - - /** - * Attempts to parse and return the OFVendorData contained in the given - * ChannelBuffer, beginning right after the vendor id. - * @param vendorId the vendor id that was parsed from the OFVendor message. - * @param data the ChannelBuffer from which to parse the vendor data - * @param length the length to the end of the enclosing message. - * @return an OFVendorData instance - */ - public OFVendorData parseVendorData(int vendorId, ChannelBuffer data, - int length); -} diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java deleted file mode 100644 index 23614b0d0eccdfe23184973ddb57f790b7ff48c3..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java +++ /dev/null @@ -1,28 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.factory; - -/** - * Classes implementing this interface are expected to be instantiated with an - * instance of an OFVendorDataFactory - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public interface OFVendorDataFactoryAware { - public void setVendorDataFactory(OFVendorDataFactory vendorDataFactory); -} diff --git a/src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java b/src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java deleted file mode 100644 index 1102dc78653263a2e33a4967b8d4a3935f44df67..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java +++ /dev/null @@ -1,57 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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 org.openflow.protocol.serializers; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.util.HexString; - -public class OFFeaturesReplyJSONSerializer extends JsonSerializer<OFFeaturesReply> { - - /** - * Performs the serialization of a OFFeaturesReply object - */ - @Override - public void serialize(OFFeaturesReply reply, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException { - jGen.writeStartObject(); - jGen.writeNumberField("actions", reply.getActions()); - jGen.writeNumberField("buffers", reply.getBuffers()); - jGen.writeNumberField("capabilities", reply.getCapabilities()); - jGen.writeStringField("datapathId", HexString.toHexString(reply.getDatapathId())); - jGen.writeNumberField("length", reply.getLength()); - serializer.defaultSerializeField("ports", reply.getPorts(), jGen); - jGen.writeNumberField("tables", reply.getTables()); - jGen.writeStringField("type", reply.getType().toString()); - jGen.writeNumberField("version", reply.getVersion()); - jGen.writeNumberField("xid", reply.getXid()); - jGen.writeEndObject(); - } - - /** - * Tells SimpleModule that we are the serializer for OFFeaturesReply - */ - @Override - public Class<OFFeaturesReply> handledType() { - return OFFeaturesReply.class; - } -} diff --git a/src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java b/src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java deleted file mode 100644 index 2ae2d1c467d095491b88d8c78a15479ed04bdbae..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java +++ /dev/null @@ -1,91 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* 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 org.openflow.protocol.serializers; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import org.openflow.protocol.OFMatch; -import org.openflow.util.HexString; - -public class OFMatchJSONSerializer extends JsonSerializer<OFMatch> { - - /** - * Converts an IP in a 32 bit integer to a dotted-decimal string - * @param i The IP address in a 32 bit integer - * @return An IP address string in dotted-decimal - */ - private String intToIp(int i) { - return ((i >> 24 ) & 0xFF) + "." + - ((i >> 16 ) & 0xFF) + "." + - ((i >> 8 ) & 0xFF) + "." + - ( i & 0xFF); - } - - /** - * Performs the serialization of a OFMatch object - */ - @Override - public void serialize(OFMatch match, JsonGenerator jGen, - SerializerProvider serializer) - throws IOException, JsonProcessingException { - jGen.writeStartObject(); - jGen.writeStringField("dataLayerDestination", - HexString.toHexString(match.getDataLayerDestination())); - jGen.writeStringField("dataLayerSource", - HexString.toHexString(match.getDataLayerSource())); - String dataType = Integer.toHexString(match.getDataLayerType()); - while (dataType.length() < 4) { - dataType = "0".concat(dataType); - } - jGen.writeStringField("dataLayerType", "0x" + dataType); - jGen.writeNumberField("dataLayerVirtualLan", - match.getDataLayerVirtualLan()); - jGen.writeNumberField("dataLayerVirtualLanPriorityCodePoint", - match.getDataLayerVirtualLanPriorityCodePoint()); - jGen.writeNumberField("inputPort", match.getInputPort()); - jGen.writeStringField("networkDestination", - intToIp(match.getNetworkDestination())); - jGen.writeNumberField("networkDestinationMaskLen", - match.getNetworkDestinationMaskLen()); - jGen.writeNumberField("networkProtocol", match.getNetworkProtocol()); - jGen.writeStringField("networkSource", - intToIp(match.getNetworkSource())); - jGen.writeNumberField("networkSourceMaskLen", - match.getNetworkSourceMaskLen()); - jGen.writeNumberField("networkTypeOfService", - match.getNetworkTypeOfService()); - jGen.writeNumberField("transportDestination", - match.getTransportDestination()); - jGen.writeNumberField("transportSource", - match.getTransportSource()); - jGen.writeNumberField("wildcards", match.getWildcards()); - jGen.writeEndObject(); - } - - /** - * Tells SimpleModule that we are the serializer for OFMatch - */ - @Override - public Class<OFMatch> handledType() { - return OFMatch.class; - } -} diff --git a/src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java b/src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java deleted file mode 100644 index 60c5a664e828508323c68657ec0663b6ab658152..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.openflow.protocol.serializers; - -import java.io.IOException; - -import org.openflow.util.HexString; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; - -public class StringDpidToLongJSONDeserializer extends - JsonDeserializer<Long> { - - @Override - public Long deserialize(JsonParser jsonParser, - DeserializationContext cntx) - throws IOException, - JsonProcessingException { - return Long.valueOf(HexString.toLong(jsonParser.getText())); - } - -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java deleted file mode 100644 index 0c86006b0919e1a87120ab96dec2caed96cd48da..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java +++ /dev/null @@ -1,130 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import com.fasterxml.jackson.annotation.JsonIgnore; -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_aggregate_stats_reply structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFAggregateStatisticsReply implements OFStatistics { - protected long packetCount; - protected long byteCount; - protected int flowCount; - - /** - * @return the packetCount - */ - public long getPacketCount() { - return packetCount; - } - - /** - * @param packetCount the packetCount to set - */ - public void setPacketCount(long packetCount) { - this.packetCount = packetCount; - } - - /** - * @return the byteCount - */ - public long getByteCount() { - return byteCount; - } - - /** - * @param byteCount the byteCount to set - */ - public void setByteCount(long byteCount) { - this.byteCount = byteCount; - } - - /** - * @return the flowCount - */ - public int getFlowCount() { - return flowCount; - } - - /** - * @param flowCount the flowCount to set - */ - public void setFlowCount(int flowCount) { - this.flowCount = flowCount; - } - - @Override - @JsonIgnore - public int getLength() { - return 24; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.packetCount = data.readLong(); - this.byteCount = data.readLong(); - this.flowCount = data.readInt(); - data.readInt(); // pad - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeLong(this.packetCount); - data.writeLong(this.byteCount); - data.writeInt(this.flowCount); - data.writeInt(0); // pad - } - - @Override - public int hashCode() { - final int prime = 397; - int result = 1; - result = prime * result + (int) (byteCount ^ (byteCount >>> 32)); - result = prime * result + flowCount; - result = prime * result + (int) (packetCount ^ (packetCount >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFAggregateStatisticsReply)) { - return false; - } - OFAggregateStatisticsReply other = (OFAggregateStatisticsReply) obj; - if (byteCount != other.byteCount) { - return false; - } - if (flowCount != other.flowCount) { - return false; - } - if (packetCount != other.packetCount) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java deleted file mode 100644 index f41a4f1d57c15a341aeb66f54cc0a87cf011ec61..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java +++ /dev/null @@ -1,135 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFMatch; - -/** - * Represents an ofp_aggregate_stats_request structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFAggregateStatisticsRequest implements OFStatistics { - protected OFMatch match; - protected byte tableId; - protected short outPort; - - /** - * @return the match - */ - public OFMatch getMatch() { - return match; - } - - /** - * @param match the match to set - */ - public void setMatch(OFMatch match) { - this.match = match; - } - - /** - * @return the tableId - */ - public byte getTableId() { - return tableId; - } - - /** - * @param tableId the tableId to set - */ - public void setTableId(byte tableId) { - this.tableId = tableId; - } - - /** - * @return the outPort - */ - public short getOutPort() { - return outPort; - } - - /** - * @param outPort the outPort to set - */ - public void setOutPort(short outPort) { - this.outPort = outPort; - } - - @Override - public int getLength() { - return 44; - } - - @Override - public void readFrom(ChannelBuffer data) { - if (this.match == null) - this.match = new OFMatch(); - this.match.readFrom(data); - this.tableId = data.readByte(); - data.readByte(); // pad - this.outPort = data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - this.match.writeTo(data); - data.writeByte(this.tableId); - data.writeByte((byte) 0); - data.writeShort(this.outPort); - } - - @Override - public int hashCode() { - final int prime = 401; - int result = 1; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime * result + outPort; - result = prime * result + tableId; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFAggregateStatisticsRequest)) { - return false; - } - OFAggregateStatisticsRequest other = (OFAggregateStatisticsRequest) obj; - if (match == null) { - if (other.match != null) { - return false; - } - } else if (!match.equals(other.match)) { - return false; - } - if (outPort != other.outPort) { - return false; - } - if (tableId != other.tableId) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java deleted file mode 100644 index 5e6586f0dfd00d71ac89aee183e9cc8e0d299ba8..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java +++ /dev/null @@ -1,246 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.StringByteSerializer; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * Represents an ofp_desc_stats structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFDescriptionStatistics implements OFStatistics { - public static int DESCRIPTION_STRING_LENGTH = 256; - public static int SERIAL_NUMBER_LENGTH = 32; - - protected String manufacturerDescription; - protected String hardwareDescription; - protected String softwareDescription; - protected String serialNumber; - protected String datapathDescription; - - - /** - * - */ - public OFDescriptionStatistics() { - } - - /** - * Copy constructor - */ - public OFDescriptionStatistics(OFDescriptionStatistics other) { - manufacturerDescription = other.manufacturerDescription; - hardwareDescription = other.hardwareDescription; - softwareDescription = other.softwareDescription; - serialNumber = other.serialNumber; - datapathDescription = other.datapathDescription; - } - - /** - * @return the manufacturerDescription - */ - public String getManufacturerDescription() { - return manufacturerDescription; - } - - /** - * @param manufacturerDescription the manufacturerDescription to set - */ - public void setManufacturerDescription(String manufacturerDescription) { - this.manufacturerDescription = manufacturerDescription; - } - - /** - * @return the hardwareDescription - */ - public String getHardwareDescription() { - return hardwareDescription; - } - - /** - * @param hardwareDescription the hardwareDescription to set - */ - public void setHardwareDescription(String hardwareDescription) { - this.hardwareDescription = hardwareDescription; - } - - /** - * @return the softwareDescription - */ - public String getSoftwareDescription() { - return softwareDescription; - } - - /** - * @param softwareDescription the softwareDescription to set - */ - public void setSoftwareDescription(String softwareDescription) { - this.softwareDescription = softwareDescription; - } - - /** - * @return the serialNumber - */ - public String getSerialNumber() { - return serialNumber; - } - - /** - * @param serialNumber the serialNumber to set - */ - public void setSerialNumber(String serialNumber) { - this.serialNumber = serialNumber; - } - - /** - * @return the datapathDescription - */ - public String getDatapathDescription() { - return datapathDescription; - } - - /** - * @param datapathDescription the datapathDescription to set - */ - public void setDatapathDescription(String datapathDescription) { - this.datapathDescription = datapathDescription; - } - - @Override - @JsonIgnore - public int getLength() { - return 1056; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.manufacturerDescription = StringByteSerializer.readFrom(data, - DESCRIPTION_STRING_LENGTH); - this.hardwareDescription = StringByteSerializer.readFrom(data, - DESCRIPTION_STRING_LENGTH); - this.softwareDescription = StringByteSerializer.readFrom(data, - DESCRIPTION_STRING_LENGTH); - this.serialNumber = StringByteSerializer.readFrom(data, - SERIAL_NUMBER_LENGTH); - this.datapathDescription = StringByteSerializer.readFrom(data, - DESCRIPTION_STRING_LENGTH); - } - - @Override - public void writeTo(ChannelBuffer data) { - StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH, - this.manufacturerDescription); - StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH, - this.hardwareDescription); - StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH, - this.softwareDescription); - StringByteSerializer.writeTo(data, SERIAL_NUMBER_LENGTH, - this.serialNumber); - StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH, - this.datapathDescription); - } - - @Override - public int hashCode() { - final int prime = 409; - int result = 1; - result = prime - * result - + ((datapathDescription == null) ? 0 : datapathDescription - .hashCode()); - result = prime - * result - + ((hardwareDescription == null) ? 0 : hardwareDescription - .hashCode()); - result = prime - * result - + ((manufacturerDescription == null) ? 0 - : manufacturerDescription.hashCode()); - result = prime * result - + ((serialNumber == null) ? 0 : serialNumber.hashCode()); - result = prime - * result - + ((softwareDescription == null) ? 0 : softwareDescription - .hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFDescriptionStatistics)) { - return false; - } - OFDescriptionStatistics other = (OFDescriptionStatistics) obj; - if (datapathDescription == null) { - if (other.datapathDescription != null) { - return false; - } - } else if (!datapathDescription.equals(other.datapathDescription)) { - return false; - } - if (hardwareDescription == null) { - if (other.hardwareDescription != null) { - return false; - } - } else if (!hardwareDescription.equals(other.hardwareDescription)) { - return false; - } - if (manufacturerDescription == null) { - if (other.manufacturerDescription != null) { - return false; - } - } else if (!manufacturerDescription - .equals(other.manufacturerDescription)) { - return false; - } - if (serialNumber == null) { - if (other.serialNumber != null) { - return false; - } - } else if (!serialNumber.equals(other.serialNumber)) { - return false; - } - if (softwareDescription == null) { - if (other.softwareDescription != null) { - return false; - } - } else if (!softwareDescription.equals(other.softwareDescription)) { - return false; - } - return true; - } - - @Override - public String toString() { - return "Switch Desc - Vendor: " + manufacturerDescription + - " Model: " + hardwareDescription + - " Make: " + datapathDescription + - " Version: " + softwareDescription + - " S/N: " + serialNumber; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java deleted file mode 100644 index 0aad88df7af5355aabe44df5278cba8fe42f019a..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java +++ /dev/null @@ -1,359 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.factory.OFActionFactory; -import org.openflow.protocol.factory.OFActionFactoryAware; -import org.openflow.util.U16; - -/** - * Represents an ofp_flow_stats structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFFlowStatisticsReply implements OFStatistics, OFActionFactoryAware { - public static int MINIMUM_LENGTH = 88; - - protected OFActionFactory actionFactory; - protected short length = (short) MINIMUM_LENGTH; - protected byte tableId; - protected OFMatch match; - protected int durationSeconds; - protected int durationNanoseconds; - protected short priority; - protected short idleTimeout; - protected short hardTimeout; - protected long cookie; - protected long packetCount; - protected long byteCount; - protected List<OFAction> actions; - - /** - * @return the tableId - */ - public byte getTableId() { - return tableId; - } - - /** - * @param tableId the tableId to set - */ - public void setTableId(byte tableId) { - this.tableId = tableId; - } - - /** - * @return the match - */ - public OFMatch getMatch() { - return match; - } - - /** - * @param match the match to set - */ - public void setMatch(OFMatch match) { - this.match = match; - } - - /** - * @return the durationSeconds - */ - public int getDurationSeconds() { - return durationSeconds; - } - - /** - * @param durationSeconds the durationSeconds to set - */ - public void setDurationSeconds(int durationSeconds) { - this.durationSeconds = durationSeconds; - } - - /** - * @return the durationNanoseconds - */ - public int getDurationNanoseconds() { - return durationNanoseconds; - } - - /** - * @param durationNanoseconds the durationNanoseconds to set - */ - public void setDurationNanoseconds(int durationNanoseconds) { - this.durationNanoseconds = durationNanoseconds; - } - - /** - * @return the priority - */ - public short getPriority() { - return priority; - } - - /** - * @param priority the priority to set - */ - public void setPriority(short priority) { - this.priority = priority; - } - - /** - * @return the idleTimeout - */ - public short getIdleTimeout() { - return idleTimeout; - } - - /** - * @param idleTimeout the idleTimeout to set - */ - public void setIdleTimeout(short idleTimeout) { - this.idleTimeout = idleTimeout; - } - - /** - * @return the hardTimeout - */ - public short getHardTimeout() { - return hardTimeout; - } - - /** - * @param hardTimeout the hardTimeout to set - */ - public void setHardTimeout(short hardTimeout) { - this.hardTimeout = hardTimeout; - } - - /** - * @return the cookie - */ - public long getCookie() { - return cookie; - } - - /** - * @param cookie the cookie to set - */ - public void setCookie(long cookie) { - this.cookie = cookie; - } - - /** - * @return the packetCount - */ - public long getPacketCount() { - return packetCount; - } - - /** - * @param packetCount the packetCount to set - */ - public void setPacketCount(long packetCount) { - this.packetCount = packetCount; - } - - /** - * @return the byteCount - */ - public long getByteCount() { - return byteCount; - } - - /** - * @param byteCount the byteCount to set - */ - public void setByteCount(long byteCount) { - this.byteCount = byteCount; - } - - /** - * @param length the length to set - */ - public void setLength(short length) { - this.length = length; - } - - @Override - @JsonIgnore - public int getLength() { - return U16.f(length); - } - - /** - * @param actionFactory the actionFactory to set - */ - @Override - public void setActionFactory(OFActionFactory actionFactory) { - this.actionFactory = actionFactory; - } - - /** - * @return the actions - */ - public List<OFAction> getActions() { - return actions; - } - - /** - * @param actions the actions to set - */ - public void setActions(List<OFAction> actions) { - this.actions = actions; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.length = data.readShort(); - this.tableId = data.readByte(); - data.readByte(); // pad - if (this.match == null) - this.match = new OFMatch(); - this.match.readFrom(data); - this.durationSeconds = data.readInt(); - this.durationNanoseconds = data.readInt(); - this.priority = data.readShort(); - this.idleTimeout = data.readShort(); - this.hardTimeout = data.readShort(); - data.readInt(); // pad - data.readShort(); // pad - this.cookie = data.readLong(); - this.packetCount = data.readLong(); - this.byteCount = data.readLong(); - if (this.actionFactory == null) - throw new RuntimeException("OFActionFactory not set"); - this.actions = this.actionFactory.parseActions(data, getLength() - - MINIMUM_LENGTH); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeShort(this.length); - data.writeByte(this.tableId); - data.writeByte((byte) 0); - this.match.writeTo(data); - data.writeInt(this.durationSeconds); - data.writeInt(this.durationNanoseconds); - data.writeShort(this.priority); - data.writeShort(this.idleTimeout); - data.writeShort(this.hardTimeout); - data.writeInt(0); // pad - data.writeShort((short)0); // pad - data.writeLong(this.cookie); - data.writeLong(this.packetCount); - data.writeLong(this.byteCount); - if (actions != null) { - for (OFAction action : actions) { - action.writeTo(data); - } - } - } - - @Override - public String toString() { - String str = "match=" + this.match; - str += " tableId=" + this.tableId; - str += " durationSeconds=" + this.durationSeconds; - str += " durationNanoseconds=" + this.durationNanoseconds; - str += " priority=" + this.priority; - str += " idleTimeout=" + this.idleTimeout; - str += " hardTimeout=" + this.hardTimeout; - str += " cookie=" + Long.toHexString(this.cookie); - str += " packetCount=" + this.packetCount; - str += " byteCount=" + this.byteCount; - str += " action=" + this.actions; - - return str; - } - - @Override - public int hashCode() { - final int prime = 419; - int result = 1; - result = prime * result + (int) (byteCount ^ (byteCount >>> 32)); - result = prime * result + (int) (cookie ^ (cookie >>> 32)); - result = prime * result + durationNanoseconds; - result = prime * result + durationSeconds; - result = prime * result + hardTimeout; - result = prime * result + idleTimeout; - result = prime * result + length; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime * result + (int) (packetCount ^ (packetCount >>> 32)); - result = prime * result + priority; - result = prime * result + tableId; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFFlowStatisticsReply)) { - return false; - } - OFFlowStatisticsReply other = (OFFlowStatisticsReply) obj; - if (byteCount != other.byteCount) { - return false; - } - if (cookie != other.cookie) { - return false; - } - if (durationNanoseconds != other.durationNanoseconds) { - return false; - } - if (durationSeconds != other.durationSeconds) { - return false; - } - if (hardTimeout != other.hardTimeout) { - return false; - } - if (idleTimeout != other.idleTimeout) { - return false; - } - if (length != other.length) { - return false; - } - if (match == null) { - if (other.match != null) { - return false; - } - } else if (!match.equals(other.match)) { - return false; - } - if (packetCount != other.packetCount) { - return false; - } - if (priority != other.priority) { - return false; - } - if (tableId != other.tableId) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java deleted file mode 100644 index b21de0c7f158298533b3bd8605954ae408282184..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java +++ /dev/null @@ -1,135 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFMatch; - -/** - * Represents an ofp_flow_stats_request structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFFlowStatisticsRequest implements OFStatistics { - protected OFMatch match; - protected byte tableId; - protected short outPort; - - /** - * @return the match - */ - public OFMatch getMatch() { - return match; - } - - /** - * @param match the match to set - */ - public void setMatch(OFMatch match) { - this.match = match; - } - - /** - * @return the tableId - */ - public byte getTableId() { - return tableId; - } - - /** - * @param tableId the tableId to set - */ - public void setTableId(byte tableId) { - this.tableId = tableId; - } - - /** - * @return the outPort - */ - public short getOutPort() { - return outPort; - } - - /** - * @param outPort the outPort to set - */ - public void setOutPort(short outPort) { - this.outPort = outPort; - } - - @Override - public int getLength() { - return 44; - } - - @Override - public void readFrom(ChannelBuffer data) { - if (this.match == null) - this.match = new OFMatch(); - this.match.readFrom(data); - this.tableId = data.readByte(); - data.readByte(); // pad - this.outPort = data.readShort(); - } - - @Override - public void writeTo(ChannelBuffer data) { - this.match.writeTo(data); - data.writeByte(this.tableId); - data.writeByte((byte) 0); - data.writeShort(this.outPort); - } - - @Override - public int hashCode() { - final int prime = 421; - int result = 1; - result = prime * result + ((match == null) ? 0 : match.hashCode()); - result = prime * result + outPort; - result = prime * result + tableId; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFFlowStatisticsRequest)) { - return false; - } - OFFlowStatisticsRequest other = (OFFlowStatisticsRequest) obj; - if (match == null) { - if (other.match != null) { - return false; - } - } else if (!match.equals(other.match)) { - return false; - } - if (outPort != other.outPort) { - return false; - } - if (tableId != other.tableId) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java deleted file mode 100644 index 15192bbc4d495fa4fd1f8f064adf0058f348d581..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java +++ /dev/null @@ -1,356 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import net.floodlightcontroller.core.web.serializers.UShortSerializer; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_port_stats structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFPortStatisticsReply implements OFStatistics { - protected short portNumber; - protected long receivePackets; - protected long transmitPackets; - protected long receiveBytes; - protected long transmitBytes; - protected long receiveDropped; - protected long transmitDropped; - protected long receiveErrors; - protected long transmitErrors; - protected long receiveFrameErrors; - protected long receiveOverrunErrors; - protected long receiveCRCErrors; - protected long collisions; - - /** - * @return the portNumber - */ - @JsonSerialize(using=UShortSerializer.class) - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - /** - * @return the receivePackets - */ - public long getreceivePackets() { - return receivePackets; - } - - /** - * @param receivePackets the receivePackets to set - */ - public void setreceivePackets(long receivePackets) { - this.receivePackets = receivePackets; - } - - /** - * @return the transmitPackets - */ - public long getTransmitPackets() { - return transmitPackets; - } - - /** - * @param transmitPackets the transmitPackets to set - */ - public void setTransmitPackets(long transmitPackets) { - this.transmitPackets = transmitPackets; - } - - /** - * @return the receiveBytes - */ - public long getReceiveBytes() { - return receiveBytes; - } - - /** - * @param receiveBytes the receiveBytes to set - */ - public void setReceiveBytes(long receiveBytes) { - this.receiveBytes = receiveBytes; - } - - /** - * @return the transmitBytes - */ - public long getTransmitBytes() { - return transmitBytes; - } - - /** - * @param transmitBytes the transmitBytes to set - */ - public void setTransmitBytes(long transmitBytes) { - this.transmitBytes = transmitBytes; - } - - /** - * @return the receiveDropped - */ - public long getReceiveDropped() { - return receiveDropped; - } - - /** - * @param receiveDropped the receiveDropped to set - */ - public void setReceiveDropped(long receiveDropped) { - this.receiveDropped = receiveDropped; - } - - /** - * @return the transmitDropped - */ - public long getTransmitDropped() { - return transmitDropped; - } - - /** - * @param transmitDropped the transmitDropped to set - */ - public void setTransmitDropped(long transmitDropped) { - this.transmitDropped = transmitDropped; - } - - /** - * @return the receiveErrors - */ - public long getreceiveErrors() { - return receiveErrors; - } - - /** - * @param receiveErrors the receiveErrors to set - */ - public void setreceiveErrors(long receiveErrors) { - this.receiveErrors = receiveErrors; - } - - /** - * @return the transmitErrors - */ - public long getTransmitErrors() { - return transmitErrors; - } - - /** - * @param transmitErrors the transmitErrors to set - */ - public void setTransmitErrors(long transmitErrors) { - this.transmitErrors = transmitErrors; - } - - /** - * @return the receiveFrameErrors - */ - public long getReceiveFrameErrors() { - return receiveFrameErrors; - } - - /** - * @param receiveFrameErrors the receiveFrameErrors to set - */ - public void setReceiveFrameErrors(long receiveFrameErrors) { - this.receiveFrameErrors = receiveFrameErrors; - } - - /** - * @return the receiveOverrunErrors - */ - public long getReceiveOverrunErrors() { - return receiveOverrunErrors; - } - - /** - * @param receiveOverrunErrors the receiveOverrunErrors to set - */ - public void setReceiveOverrunErrors(long receiveOverrunErrors) { - this.receiveOverrunErrors = receiveOverrunErrors; - } - - /** - * @return the receiveCRCErrors - */ - public long getReceiveCRCErrors() { - return receiveCRCErrors; - } - - /** - * @param receiveCRCErrors the receiveCRCErrors to set - */ - public void setReceiveCRCErrors(long receiveCRCErrors) { - this.receiveCRCErrors = receiveCRCErrors; - } - - /** - * @return the collisions - */ - public long getCollisions() { - return collisions; - } - - /** - * @param collisions the collisions to set - */ - public void setCollisions(long collisions) { - this.collisions = collisions; - } - - @Override - @JsonIgnore - public int getLength() { - return 104; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.portNumber = data.readShort(); - data.readShort(); // pad - data.readInt(); // pad - this.receivePackets = data.readLong(); - this.transmitPackets = data.readLong(); - this.receiveBytes = data.readLong(); - this.transmitBytes = data.readLong(); - this.receiveDropped = data.readLong(); - this.transmitDropped = data.readLong(); - this.receiveErrors = data.readLong(); - this.transmitErrors = data.readLong(); - this.receiveFrameErrors = data.readLong(); - this.receiveOverrunErrors = data.readLong(); - this.receiveCRCErrors = data.readLong(); - this.collisions = data.readLong(); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeShort(this.portNumber); - data.writeShort((short) 0); // pad - data.writeInt(0); // pad - data.writeLong(this.receivePackets); - data.writeLong(this.transmitPackets); - data.writeLong(this.receiveBytes); - data.writeLong(this.transmitBytes); - data.writeLong(this.receiveDropped); - data.writeLong(this.transmitDropped); - data.writeLong(this.receiveErrors); - data.writeLong(this.transmitErrors); - data.writeLong(this.receiveFrameErrors); - data.writeLong(this.receiveOverrunErrors); - data.writeLong(this.receiveCRCErrors); - data.writeLong(this.collisions); - } - - @Override - public int hashCode() { - final int prime = 431; - int result = 1; - result = prime * result + (int) (collisions ^ (collisions >>> 32)); - result = prime * result + portNumber; - result = prime * result - + (int) (receivePackets ^ (receivePackets >>> 32)); - result = prime * result + (int) (receiveBytes ^ (receiveBytes >>> 32)); - result = prime * result - + (int) (receiveCRCErrors ^ (receiveCRCErrors >>> 32)); - result = prime * result - + (int) (receiveDropped ^ (receiveDropped >>> 32)); - result = prime * result - + (int) (receiveFrameErrors ^ (receiveFrameErrors >>> 32)); - result = prime * result - + (int) (receiveOverrunErrors ^ (receiveOverrunErrors >>> 32)); - result = prime * result - + (int) (receiveErrors ^ (receiveErrors >>> 32)); - result = prime * result - + (int) (transmitBytes ^ (transmitBytes >>> 32)); - result = prime * result - + (int) (transmitDropped ^ (transmitDropped >>> 32)); - result = prime * result - + (int) (transmitErrors ^ (transmitErrors >>> 32)); - result = prime * result - + (int) (transmitPackets ^ (transmitPackets >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFPortStatisticsReply)) { - return false; - } - OFPortStatisticsReply other = (OFPortStatisticsReply) obj; - if (collisions != other.collisions) { - return false; - } - if (portNumber != other.portNumber) { - return false; - } - if (receivePackets != other.receivePackets) { - return false; - } - if (receiveBytes != other.receiveBytes) { - return false; - } - if (receiveCRCErrors != other.receiveCRCErrors) { - return false; - } - if (receiveDropped != other.receiveDropped) { - return false; - } - if (receiveFrameErrors != other.receiveFrameErrors) { - return false; - } - if (receiveOverrunErrors != other.receiveOverrunErrors) { - return false; - } - if (receiveErrors != other.receiveErrors) { - return false; - } - if (transmitBytes != other.transmitBytes) { - return false; - } - if (transmitDropped != other.transmitDropped) { - return false; - } - if (transmitErrors != other.transmitErrors) { - return false; - } - if (transmitPackets != other.transmitPackets) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java deleted file mode 100644 index c07a895afeb355678db7bf7251e12054369c1c92..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java +++ /dev/null @@ -1,88 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_port_stats_request structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFPortStatisticsRequest implements OFStatistics { - protected short portNumber; - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - @Override - public int getLength() { - return 8; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.portNumber = data.readShort(); - data.readShort(); // pad - data.readInt(); // pad - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeShort(this.portNumber); - data.writeShort((short) 0); // pad - data.writeInt(0); // pad - } - - @Override - public int hashCode() { - final int prime = 433; - int result = 1; - result = prime * result + portNumber; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFPortStatisticsRequest)) { - return false; - } - OFPortStatisticsRequest other = (OFPortStatisticsRequest) obj; - if (portNumber != other.portNumber) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java deleted file mode 100644 index 34a9e18200bc73ff5a7d628c671bb641cd243068..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java +++ /dev/null @@ -1,175 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import com.fasterxml.jackson.annotation.JsonIgnore; -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_queue_stats structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFQueueStatisticsReply implements OFStatistics { - protected short portNumber; - protected int queueId; - protected long transmitBytes; - protected long transmitPackets; - protected long transmitErrors; - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - /** - * @return the queueId - */ - public int getQueueId() { - return queueId; - } - - /** - * @param queueId the queueId to set - */ - public void setQueueId(int queueId) { - this.queueId = queueId; - } - - /** - * @return the transmitBytes - */ - public long getTransmitBytes() { - return transmitBytes; - } - - /** - * @param transmitBytes the transmitBytes to set - */ - public void setTransmitBytes(long transmitBytes) { - this.transmitBytes = transmitBytes; - } - - /** - * @return the transmitPackets - */ - public long getTransmitPackets() { - return transmitPackets; - } - - /** - * @param transmitPackets the transmitPackets to set - */ - public void setTransmitPackets(long transmitPackets) { - this.transmitPackets = transmitPackets; - } - - /** - * @return the transmitErrors - */ - public long getTransmitErrors() { - return transmitErrors; - } - - /** - * @param transmitErrors the transmitErrors to set - */ - public void setTransmitErrors(long transmitErrors) { - this.transmitErrors = transmitErrors; - } - - @Override - @JsonIgnore - public int getLength() { - return 32; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.portNumber = data.readShort(); - data.readShort(); // pad - this.queueId = data.readInt(); - this.transmitBytes = data.readLong(); - this.transmitPackets = data.readLong(); - this.transmitErrors = data.readLong(); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeShort(this.portNumber); - data.writeShort((short) 0); // pad - data.writeInt(this.queueId); - data.writeLong(this.transmitBytes); - data.writeLong(this.transmitPackets); - data.writeLong(this.transmitErrors); - } - - @Override - public int hashCode() { - final int prime = 439; - int result = 1; - result = prime * result + portNumber; - result = prime * result + queueId; - result = prime * result - + (int) (transmitBytes ^ (transmitBytes >>> 32)); - result = prime * result - + (int) (transmitErrors ^ (transmitErrors >>> 32)); - result = prime * result - + (int) (transmitPackets ^ (transmitPackets >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFQueueStatisticsReply)) { - return false; - } - OFQueueStatisticsReply other = (OFQueueStatisticsReply) obj; - if (portNumber != other.portNumber) { - return false; - } - if (queueId != other.queueId) { - return false; - } - if (transmitBytes != other.transmitBytes) { - return false; - } - if (transmitErrors != other.transmitErrors) { - return false; - } - if (transmitPackets != other.transmitPackets) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java deleted file mode 100644 index 33314539f62b1bbb21e59a92c07712e653b2584e..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java +++ /dev/null @@ -1,107 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Represents an ofp_queue_stats_request structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFQueueStatisticsRequest implements OFStatistics { - protected short portNumber; - protected int queueId; - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param portNumber the portNumber to set - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - /** - * @return the queueId - */ - public int getQueueId() { - return queueId; - } - - /** - * @param queueId the queueId to set - */ - public void setQueueId(int queueId) { - this.queueId = queueId; - } - - @Override - public int getLength() { - return 8; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.portNumber = data.readShort(); - data.readShort(); // pad - this.queueId = data.readInt(); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeShort(this.portNumber); - data.writeShort((short) 0); // pad - data.writeInt(this.queueId); - } - - @Override - public int hashCode() { - final int prime = 443; - int result = 1; - result = prime * result + portNumber; - result = prime * result + queueId; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFQueueStatisticsRequest)) { - return false; - } - OFQueueStatisticsRequest other = (OFQueueStatisticsRequest) obj; - if (portNumber != other.portNumber) { - return false; - } - if (queueId != other.queueId) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFStatistics.java deleted file mode 100644 index 5e8f4dd3f84949b602f977d3c983a81af0e04383..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFStatistics.java +++ /dev/null @@ -1,45 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * The base class for all OpenFlow statistics. - * - * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010 - */ -public interface OFStatistics { - /** - * Returns the wire length of this message in bytes - * @return the length - */ - public int getLength(); - - /** - * Read this message off the wire from the specified ByteBuffer - * @param data - */ - public void readFrom(ChannelBuffer data); - - /** - * Write this message's binary format to the specified ByteBuffer - * @param data - */ - public void writeTo(ChannelBuffer data); -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java b/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java deleted file mode 100644 index f2b9e3015263345a44bac8c9ffbc88c1a6d4fe5b..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java +++ /dev/null @@ -1,317 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - -import java.lang.reflect.Constructor; - -import org.openflow.protocol.Instantiable; -import org.openflow.protocol.OFType; - -public enum OFStatisticsType { - DESC (0, OFDescriptionStatistics.class, OFDescriptionStatistics.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFDescriptionStatistics(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFDescriptionStatistics(); - } - }), - FLOW (1, OFFlowStatisticsRequest.class, OFFlowStatisticsReply.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFFlowStatisticsRequest(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFFlowStatisticsReply(); - } - }), - AGGREGATE (2, OFAggregateStatisticsRequest.class, OFAggregateStatisticsReply.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFAggregateStatisticsRequest(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFAggregateStatisticsReply(); - } - }), - TABLE (3, OFTableStatistics.class, OFTableStatistics.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFTableStatistics(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFTableStatistics(); - } - }), - PORT (4, OFPortStatisticsRequest.class, OFPortStatisticsReply.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFPortStatisticsRequest(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFPortStatisticsReply(); - } - }), - QUEUE (5, OFQueueStatisticsRequest.class, OFQueueStatisticsReply.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFQueueStatisticsRequest(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFQueueStatisticsReply(); - } - }), - VENDOR (0xffff, OFVendorStatistics.class, OFVendorStatistics.class, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFVendorStatistics(); - } - }, - new Instantiable<OFStatistics>() { - @Override - public OFStatistics instantiate() { - return new OFVendorStatistics(); - } - }); - - static OFStatisticsType[] requestMapping; - static OFStatisticsType[] replyMapping; - - protected Class<? extends OFStatistics> requestClass; - protected Constructor<? extends OFStatistics> requestConstructor; - protected Instantiable<OFStatistics> requestInstantiable; - protected Class<? extends OFStatistics> replyClass; - protected Constructor<? extends OFStatistics> replyConstructor; - protected Instantiable<OFStatistics> replyInstantiable; - protected short type; - - /** - * Store some information about the OpenFlow Statistic type, including wire - * protocol type number, and derived class - * - * @param type Wire protocol number associated with this OFStatisticsType - * @param requestClass The Statistics Java class to return when the - * containing OFType is STATS_REQUEST - * @param replyClass The Statistics Java class to return when the - * containing OFType is STATS_REPLY - */ - OFStatisticsType(int type, Class<? extends OFStatistics> requestClass, - Class<? extends OFStatistics> replyClass, - Instantiable<OFStatistics> requestInstantiable, - Instantiable<OFStatistics> replyInstantiable) { - this.type = (short) type; - this.requestClass = requestClass; - try { - this.requestConstructor = requestClass.getConstructor(new Class[]{}); - } catch (Exception e) { - throw new RuntimeException( - "Failure getting constructor for class: " + requestClass, e); - } - - this.replyClass = replyClass; - try { - this.replyConstructor = replyClass.getConstructor(new Class[]{}); - } catch (Exception e) { - throw new RuntimeException( - "Failure getting constructor for class: " + replyClass, e); - } - this.requestInstantiable = requestInstantiable; - this.replyInstantiable = replyInstantiable; - OFStatisticsType.addMapping(this.type, OFType.STATS_REQUEST, this); - OFStatisticsType.addMapping(this.type, OFType.STATS_REPLY, this); - } - - /** - * Adds a mapping from type value to OFStatisticsType enum - * - * @param i OpenFlow wire protocol type - * @param t type of containing OFMessage, only accepts STATS_REQUEST or - * STATS_REPLY - * @param st type - */ - static public void addMapping(short i, OFType t, OFStatisticsType st) { - if (i < 0) - i = (short) (16+i); - if (t == OFType.STATS_REQUEST) { - if (requestMapping == null) - requestMapping = new OFStatisticsType[16]; - OFStatisticsType.requestMapping[i] = st; - } else if (t == OFType.STATS_REPLY){ - if (replyMapping == null) - replyMapping = new OFStatisticsType[16]; - OFStatisticsType.replyMapping[i] = st; - } else { - throw new RuntimeException(t.toString() + " is an invalid OFType"); - } - } - - /** - * Remove a mapping from type value to OFStatisticsType enum - * - * @param i OpenFlow wire protocol type - * @param t type of containing OFMessage, only accepts STATS_REQUEST or - * STATS_REPLY - */ - static public void removeMapping(short i, OFType t) { - if (i < 0) - i = (short) (16+i); - if (t == OFType.STATS_REQUEST) { - requestMapping[i] = null; - } else if (t == OFType.STATS_REPLY){ - replyMapping[i] = null; - } else { - throw new RuntimeException(t.toString() + " is an invalid OFType"); - } - } - - /** - * Given a wire protocol OpenFlow type number, return the OFStatisticsType - * associated with it - * - * @param i wire protocol number - * @param t type of containing OFMessage, only accepts STATS_REQUEST or - * STATS_REPLY - * @return OFStatisticsType enum type - */ - static public OFStatisticsType valueOf(short i, OFType t) { - if (i < 0) - i = (short) (16+i); - if (t == OFType.STATS_REQUEST) { - return requestMapping[i]; - } else if (t == OFType.STATS_REPLY){ - return replyMapping[i]; - } else { - throw new RuntimeException(t.toString() + " is an invalid OFType"); - } - } - - /** - * @return Returns the wire protocol value corresponding to this - * OFStatisticsType - */ - public short getTypeValue() { - return this.type; - } - - /** - * @param t type of containing OFMessage, only accepts STATS_REQUEST or - * STATS_REPLY - * @return return the OFMessage subclass corresponding to this - * OFStatisticsType - */ - public Class<? extends OFStatistics> toClass(OFType t) { - if (t == OFType.STATS_REQUEST) { - return requestClass; - } else if (t == OFType.STATS_REPLY){ - return replyClass; - } else { - throw new RuntimeException(t.toString() + " is an invalid OFType"); - } - } - - /** - * Returns the no-argument Constructor of the implementation class for - * this OFStatisticsType, either request or reply based on the supplied - * OFType - * - * @param t - * @return - */ - public Constructor<? extends OFStatistics> getConstructor(OFType t) { - if (t == OFType.STATS_REQUEST) { - return requestConstructor; - } else if (t == OFType.STATS_REPLY) { - return replyConstructor; - } else { - throw new RuntimeException(t.toString() + " is an invalid OFType"); - } - } - - /** - * @return the requestInstantiable - */ - public Instantiable<OFStatistics> getRequestInstantiable() { - return requestInstantiable; - } - - /** - * @param requestInstantiable the requestInstantiable to set - */ - public void setRequestInstantiable( - Instantiable<OFStatistics> requestInstantiable) { - this.requestInstantiable = requestInstantiable; - } - - /** - * @return the replyInstantiable - */ - public Instantiable<OFStatistics> getReplyInstantiable() { - return replyInstantiable; - } - - /** - * @param replyInstantiable the replyInstantiable to set - */ - public void setReplyInstantiable(Instantiable<OFStatistics> replyInstantiable) { - this.replyInstantiable = replyInstantiable; - } - - /** - * Returns a new instance of the implementation class for - * this OFStatisticsType, either request or reply based on the supplied - * OFType - * - * @param t - * @return - */ - public OFStatistics newInstance(OFType t) { - if (t == OFType.STATS_REQUEST) { - return requestInstantiable.instantiate(); - } else if (t == OFType.STATS_REPLY) { - return replyInstantiable.instantiate(); - } else { - throw new RuntimeException(t.toString() + " is an invalid OFType"); - } - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java deleted file mode 100644 index 9e6d34e10bdfa16cf7f75be64d03eab22f86b26e..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java +++ /dev/null @@ -1,223 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.util.StringByteSerializer; - -/** - * Represents an ofp_table_stats structure - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFTableStatistics implements OFStatistics { - public static int MAX_TABLE_NAME_LEN = 32; - - protected byte tableId; - protected String name; - protected int wildcards; - protected int maximumEntries; - protected int activeCount; - protected long lookupCount; - protected long matchedCount; - - /** - * @return the tableId - */ - public byte getTableId() { - return tableId; - } - - /** - * @param tableId the tableId to set - */ - public void setTableId(byte tableId) { - this.tableId = tableId; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @return the wildcards - */ - public int getWildcards() { - return wildcards; - } - - /** - * @param wildcards the wildcards to set - */ - public void setWildcards(int wildcards) { - this.wildcards = wildcards; - } - - /** - * @return the maximumEntries - */ - public int getMaximumEntries() { - return maximumEntries; - } - - /** - * @param maximumEntries the maximumEntries to set - */ - public void setMaximumEntries(int maximumEntries) { - this.maximumEntries = maximumEntries; - } - - /** - * @return the activeCount - */ - public int getActiveCount() { - return activeCount; - } - - /** - * @param activeCount the activeCount to set - */ - public void setActiveCount(int activeCount) { - this.activeCount = activeCount; - } - - /** - * @return the lookupCount - */ - public long getLookupCount() { - return lookupCount; - } - - /** - * @param lookupCount the lookupCount to set - */ - public void setLookupCount(long lookupCount) { - this.lookupCount = lookupCount; - } - - /** - * @return the matchedCount - */ - public long getMatchedCount() { - return matchedCount; - } - - /** - * @param matchedCount the matchedCount to set - */ - public void setMatchedCount(long matchedCount) { - this.matchedCount = matchedCount; - } - - @Override - public int getLength() { - return 64; - } - - @Override - public void readFrom(ChannelBuffer data) { - this.tableId = data.readByte(); - data.readByte(); // pad - data.readByte(); // pad - data.readByte(); // pad - this.name = StringByteSerializer.readFrom(data, MAX_TABLE_NAME_LEN); - this.wildcards = data.readInt(); - this.maximumEntries = data.readInt(); - this.activeCount = data.readInt(); - this.lookupCount = data.readLong(); - this.matchedCount = data.readLong(); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeByte(this.tableId); - data.writeByte((byte) 0); // pad - data.writeByte((byte) 0); // pad - data.writeByte((byte) 0); // pad - StringByteSerializer.writeTo(data, MAX_TABLE_NAME_LEN, this.name); - data.writeInt(this.wildcards); - data.writeInt(this.maximumEntries); - data.writeInt(this.activeCount); - data.writeLong(this.lookupCount); - data.writeLong(this.matchedCount); - } - - @Override - public int hashCode() { - final int prime = 449; - int result = 1; - result = prime * result + activeCount; - result = prime * result + (int) (lookupCount ^ (lookupCount >>> 32)); - result = prime * result + (int) (matchedCount ^ (matchedCount >>> 32)); - result = prime * result + maximumEntries; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + tableId; - result = prime * result + wildcards; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFTableStatistics)) { - return false; - } - OFTableStatistics other = (OFTableStatistics) obj; - if (activeCount != other.activeCount) { - return false; - } - if (lookupCount != other.lookupCount) { - return false; - } - if (matchedCount != other.matchedCount) { - return false; - } - if (maximumEntries != other.maximumEntries) { - return false; - } - if (name == null) { - if (other.name != null) { - return false; - } - } else if (!name.equals(other.name)) { - return false; - } - if (tableId != other.tableId) { - return false; - } - if (wildcards != other.wildcards) { - return false; - } - return true; - } -} diff --git a/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java deleted file mode 100644 index 0257a6aab024ef55ab6b8b7d0f80a473b806ebfc..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java +++ /dev/null @@ -1,83 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol.statistics; - - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * The base class for vendor implemented statistics - * @author David Erickson (daviderickson@cs.stanford.edu) - */ -public class OFVendorStatistics implements OFStatistics { - protected int vendor; - protected byte[] body; - - // non-message fields - protected int length = 0; - - @Override - public void readFrom(ChannelBuffer data) { - this.vendor = data.readInt(); - if (body == null) - body = new byte[length - 4]; - data.readBytes(body); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeInt(this.vendor); - if (body != null) - data.writeBytes(body); - } - - @Override - public int hashCode() { - final int prime = 457; - int result = 1; - result = prime * result + vendor; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof OFVendorStatistics)) { - return false; - } - OFVendorStatistics other = (OFVendorStatistics) obj; - if (vendor != other.vendor) { - return false; - } - return true; - } - - @Override - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } -} diff --git a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java b/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java deleted file mode 100644 index 1f0e14b2dd4b6dac9f5dadc5d5c9e6a0b4a1a4a5..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java +++ /dev/null @@ -1,71 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.vendor; - -import org.openflow.protocol.Instantiable; - -/** - * Subclass of OFVendorDataType that works with any vendor data format that - * begins with a integral value to indicate the format of the remaining data. - * It maps from the per-vendor-id integral data type code to the object - * used to instantiate the class associated with that vendor data type. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFBasicVendorDataType extends OFVendorDataType { - - /** - * The data type value at the beginning of the vendor data. - */ - protected long type; - - /** - * Construct an empty (i.e. no specified data type value) vendor data type. - */ - public OFBasicVendorDataType() { - super(); - this.type = 0; - } - - /** - * Store some information about the vendor data type, including wire protocol - * type number, derived class and instantiator. - * - * @param type Wire protocol number associated with this vendor data type - * @param instantiator An Instantiator<OFVendorData> implementation that - * creates an instance of an appropriate subclass of OFVendorData. - */ - public OFBasicVendorDataType(long type, Instantiable<OFVendorData> instantiator) { - super(instantiator); - this.type = type; - } - - /** - * @return Returns the wire protocol value corresponding to this OFVendorDataType - */ - public long getTypeValue() { - return this.type; - } - - /** - * @param type the wire protocol value for this data type - */ - public void setTypeValue(long type) { - this.type = type; - } -} diff --git a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java b/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java deleted file mode 100644 index 5f789dc3f9a661c8dc84d74904b209e004bef215..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java +++ /dev/null @@ -1,162 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.vendor; - -import java.util.HashMap; -import java.util.Map; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.Instantiable; - -/** - * Basic subclass of OFVendorId that works with any vendor data format where - * the data begins with an integral data type value. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFBasicVendorId extends OFVendorId { - - /** - * The size of the data type value at the beginning of all vendor - * data associated with this vendor id. The data type size must be - * either 1, 2, 4 or 8. - */ - protected int dataTypeSize; - - /** - * Map of the vendor data types that have been registered for this - * vendor id. - */ - protected Map<Long, OFBasicVendorDataType> dataTypeMap = - new HashMap<Long, OFBasicVendorDataType>(); - - /** - * Construct an OFVendorId that where the vendor data begins - * with a data type value whose size is dataTypeSize. - * @param id the id of the vendor, typically the OUI of a vendor - * prefixed with 0. - * @param dataTypeSize the size of the integral data type value - * at the beginning of the vendor data. The value must be the - * size of an integeral data type (i.e. either 1,2,4 or 8). - */ - public OFBasicVendorId(int id, int dataTypeSize) { - super(id); - assert (dataTypeSize == 1) || (dataTypeSize == 2) || - (dataTypeSize == 4) || (dataTypeSize == 8); - this.dataTypeSize = dataTypeSize; - } - - /** - * Get the size of the data type value at the beginning of the vendor - * data. OFBasicVendorId assumes that this value is common across all of - * the vendor data formats associated with a given vendor id. - * @return - */ - public int getDataTypeSize() { - return dataTypeSize; - } - - /** - * Register a vendor data type with this vendor id. - * @param vendorDataType - */ - public void registerVendorDataType(OFBasicVendorDataType vendorDataType) { - dataTypeMap.put(vendorDataType.getTypeValue(), vendorDataType); - } - - /** - * Lookup the OFVendorDataType instance that has been registered with - * this vendor id. - * - * @param vendorDataType the integer code that was parsed from the - * @return - */ - public OFVendorDataType lookupVendorDataType(int vendorDataType) { - return dataTypeMap.get(Long.valueOf(vendorDataType)); - } - - /** - * This function parses enough of the data from the buffer to be able - * to determine the appropriate OFVendorDataType for the data. It is meant - * to be a reasonably generic implementation that will work for most - * formats of vendor extensions. If the vendor data doesn't fit the - * assumptions listed below, then this method will need to be overridden - * to implement custom parsing. - * - * This implementation assumes that the vendor data begins with a data - * type code that is used to distinguish different formats of vendor - * data associated with a particular vendor ID. - * The exact format of the data is vendor-defined, so we don't know how - * how big the code is (or really even if there is a code). This code - * assumes that the common case will be that the data does include - * an initial type code (i.e. so that the vendor can have multiple - * message/data types) and that the size is either 1, 2 or 4 bytes. - * The size of the initial type code is configured by the subclass of - * OFVendorId. - * - * @param data the channel buffer containing the vendor data. - * @param length the length to the end of the enclosing message - * @return the OFVendorDataType that can be used to instantiate the - * appropriate subclass of OFVendorData. - */ - public OFVendorDataType parseVendorDataType(ChannelBuffer data, int length) { - OFVendorDataType vendorDataType = null; - - // Parse out the type code from the vendor data. - long dataTypeValue = 0; - if ((length == 0) || (length >= dataTypeSize)) { - switch (dataTypeSize) { - case 1: - dataTypeValue = data.readByte(); - break; - case 2: - dataTypeValue = data.readShort(); - break; - case 4: - dataTypeValue = data.readInt(); - break; - case 8: - dataTypeValue = data.readLong(); - break; - default: - // This would be indicative of a coding error where the - // dataTypeSize was specified incorrectly. This should have been - // caught in the constructor for OFVendorId. - assert false; - } - - vendorDataType = dataTypeMap.get(dataTypeValue); - } - - // If we weren't able to parse/map the data to a known OFVendorDataType, - // then map it to a generic vendor data type. - if (vendorDataType == null) { - vendorDataType = new OFBasicVendorDataType(dataTypeValue, - new Instantiable<OFVendorData>() { - @Override - public OFVendorData instantiate() { - return new OFByteArrayVendorData(); - } - } - ); - } - - return vendorDataType; - } - -} diff --git a/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java b/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java deleted file mode 100644 index 08fa003172312af1569daf4eb83700fca177df2e..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java +++ /dev/null @@ -1,94 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.vendor; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Basic implementation of OFVendorData that just treats the data as a - * byte array. This is used if there's an OFVendor message where there's - * no registered OFVendorId or no specific OFVendorDataType that can be - * determined from the data. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFByteArrayVendorData implements OFVendorData { - - protected byte[] bytes; - - /** - * Construct vendor data with an empty byte array. - */ - public OFByteArrayVendorData() { - } - - /** - * Construct vendor data with the specified byte array. - * @param bytes - */ - public OFByteArrayVendorData(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Get the associated byte array for this vendor data. - * @return the byte array containing the raw vendor data. - */ - public byte[] getBytes() { - return bytes; - } - - /** - * Set the byte array for the vendor data. - * @param bytes the raw byte array containing the vendor data. - */ - public void setBytes(byte[] bytes) { - this.bytes = bytes; - } - - /** - * Get the length of the vendor data. In this case it's just then length - * of the underlying byte array. - * @return the length of the vendor data - */ - @Override - public int getLength() { - return (bytes != null) ? bytes.length : 0; - } - - /** - * Read the vendor data from the ChannelBuffer into the byte array. - * @param data the channel buffer from which we're deserializing - * @param length the length to the end of the enclosing message - */ - @Override - public void readFrom(ChannelBuffer data, int length) { - bytes = new byte[length]; - data.readBytes(bytes); - } - - /** - * Write the vendor data bytes to the ChannelBuffer - * @param data the channel buffer to which we're serializing - */ - @Override - public void writeTo(ChannelBuffer data) { - if (bytes != null) - data.writeBytes(bytes); - } -} diff --git a/src/main/java/org/openflow/protocol/vendor/OFVendorData.java b/src/main/java/org/openflow/protocol/vendor/OFVendorData.java deleted file mode 100644 index 6dfb4e6cb62b170e83b28678ac5c0669f3d6610a..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/vendor/OFVendorData.java +++ /dev/null @@ -1,44 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.vendor; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * The base class for all vendor data. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public interface OFVendorData { - /** - * @return length of the data - */ - public int getLength(); - - /** - * Read the vendor data from the specified ChannelBuffer - * @param data - */ - public void readFrom(ChannelBuffer data, int length); - - /** - * Write the vendor data to the specified ChannelBuffer - * @param data - */ - public void writeTo(ChannelBuffer data); -} diff --git a/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java b/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java deleted file mode 100644 index ecae4823925750fc8e4f6becb9d4249b1c567f85..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java +++ /dev/null @@ -1,79 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.vendor; - -import org.openflow.protocol.Instantiable; - -/** - * Class that represents a specific vendor data type format in an - * OFVendor message. Typically the vendor data will begin with an integer - * code that determines the format of the rest of the data, but this - * class does not assume that. It's basically just a holder for an - * instantiator of the appropriate subclass of OFVendorData. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFVendorDataType { - - /** - * Object that instantiates the subclass of OFVendorData - * associated with this data type. - */ - protected Instantiable<OFVendorData> instantiable; - - /** - * Construct an empty vendor data type. - */ - public OFVendorDataType() { - super(); - } - - /** - * Construct a vendor data type with the specified instantiable. - * @param instantiable object that creates the subclass of OFVendorData - * associated with this data type. - */ - public OFVendorDataType(Instantiable<OFVendorData> instantiable) { - this.instantiable = instantiable; - } - - /** - * Returns a new instance of a subclass of OFVendorData associated with - * this OFVendorDataType. - * - * @return the new object - */ - public OFVendorData newInstance() { - return instantiable.instantiate(); - } - - /** - * @return the instantiable - */ - public Instantiable<OFVendorData> getInstantiable() { - return instantiable; - } - - /** - * @param instantiable the instantiable to set - */ - public void setInstantiable(Instantiable<OFVendorData> instantiable) { - this.instantiable = instantiable; - } - -} diff --git a/src/main/java/org/openflow/protocol/vendor/OFVendorId.java b/src/main/java/org/openflow/protocol/vendor/OFVendorId.java deleted file mode 100644 index f0af8a7635088c21bd889dc0632c481fb61350ab..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/protocol/vendor/OFVendorId.java +++ /dev/null @@ -1,85 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.protocol.vendor; - -import java.util.HashMap; -import java.util.Map; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Base class for the vendor ID corresponding to vendor extensions from a - * given vendor. It is responsible for knowing how to parse out some sort of - * data type value from the vendor data in an OFVendor message so that we can - * dispatch to the different subclasses of OFVendorData corresponding to the - * different formats of data for the vendor extensions. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public abstract class OFVendorId { - static Map<Integer, OFVendorId> mapping = new HashMap<Integer, OFVendorId>(); - - /** - * The vendor id value, typically the OUI of the vendor prefixed with 0. - */ - protected int id; - - /** - * Register a new vendor id. - * @param vendorId the vendor id to register - */ - public static void registerVendorId(OFVendorId vendorId) { - mapping.put(vendorId.getId(), vendorId); - } - - /** - * Lookup the OFVendorId instance corresponding to the given id value. - * @param id the integer vendor id value - * @return the corresponding OFVendorId that's been registered for the - * given value, or null if there id has not been registered. - */ - public static OFVendorId lookupVendorId(int id) { - return mapping.get(id); - } - - /** - * Create an OFVendorId with the give vendor id value - * @param id - */ - public OFVendorId(int id) { - this.id = id; - } - - /** - * @return the vendor id value - */ - public int getId() { - return id; - } - - /** - * This function parses enough of the data from the channel buffer to be - * able to determine the appropriate OFVendorDataType for the data. - * - * @param data the channel buffer containing the vendor data. - * @param length the length to the end of the enclosing message - * @return the OFVendorDataType that can be used to instantiate the - * appropriate subclass of OFVendorData. - */ - public abstract OFVendorDataType parseVendorDataType(ChannelBuffer data, int length); -} diff --git a/src/main/java/org/openflow/util/HexString.java b/src/main/java/org/openflow/util/HexString.java deleted file mode 100644 index b5628242dadcbc7a12ccd8568f9c00b319439783..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/HexString.java +++ /dev/null @@ -1,93 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.math.BigInteger; - -public class HexString { - /** - * Convert a string of bytes to a ':' separated hex string - * @param bytes - * @return "0f:ca:fe:de:ad:be:ef" - */ - public static String toHexString(byte[] bytes) { - if (bytes == null) return ""; - int i; - String ret = ""; - String tmp; - for(i=0; i< bytes.length; i++) { - if(i> 0) - ret += ":"; - tmp = Integer.toHexString(U8.f(bytes[i])); - if (tmp.length() == 1) - ret += "0"; - ret += tmp; - } - return ret; - } - - public static String toHexString(long val, int padTo) { - char arr[] = Long.toHexString(val).toCharArray(); - String ret = ""; - // prepend the right number of leading zeros - int i = 0; - for (; i < (padTo * 2 - arr.length); i++) { - ret += "0"; - if ((i % 2) != 0) - ret += ":"; - } - for (int j = 0; j < arr.length; j++) { - ret += arr[j]; - if ((((i + j) % 2) != 0) && (j < (arr.length - 1))) - ret += ":"; - } - return ret; - } - - public static String toHexString(long val) { - return toHexString(val, 8); - } - - - /** - * Convert a string of hex values into a string of bytes - * @param values "0f:ca:fe:de:ad:be:ef" - * @return [15, 5 ,2, 5, 17] - * @throws NumberFormatException If the string can not be parsed - */ - public static byte[] fromHexString(String values) throws NumberFormatException { - String[] octets = values.split(":"); - byte[] ret = new byte[octets.length]; - - for(int i = 0; i < octets.length; i++) { - if (octets[i].length() > 2) - throw new NumberFormatException("Invalid octet length"); - ret[i] = Integer.valueOf(octets[i], 16).byteValue(); - } - return ret; - } - - public static long toLong(String values) throws NumberFormatException { - // Long.parseLong() can't handle HexStrings with MSB set. Sigh. - BigInteger bi = new BigInteger(values.replaceAll(":", ""),16); - if (bi.bitLength() > 64) - throw new NumberFormatException("Input string too big to fit in long: " + values); - return bi.longValue(); - } - -} diff --git a/src/main/java/org/openflow/util/IProducer.java b/src/main/java/org/openflow/util/IProducer.java deleted file mode 100644 index 52ae79a52b5dc47af63f71d0aceeb3ee26105727..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/IProducer.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.openflow.util; - -public interface IProducer { - - public void registerConsumer(Class<?> iface, Object anObj); - - public void deregisterConsumer(Class<?> iface, Object anObj); - -} diff --git a/src/main/java/org/openflow/util/LRULinkedHashMap.java b/src/main/java/org/openflow/util/LRULinkedHashMap.java deleted file mode 100644 index 7f05381c20bbe04760714cd8a45f3d50907c1558..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/LRULinkedHashMap.java +++ /dev/null @@ -1,42 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.util.LinkedHashMap; - -public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> { - private static final long serialVersionUID = -2964986094089626647L; - protected int maximumCapacity; - - public LRULinkedHashMap(int initialCapacity, int maximumCapacity) { - super(initialCapacity, 0.75f, true); - this.maximumCapacity = maximumCapacity; - } - - public LRULinkedHashMap(int maximumCapacity) { - super(16, 0.75f, true); - this.maximumCapacity = maximumCapacity; - } - - @Override - protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) { - if (this.size() > maximumCapacity) - return true; - return false; - } -} diff --git a/src/main/java/org/openflow/util/ProducerConsumer.java b/src/main/java/org/openflow/util/ProducerConsumer.java deleted file mode 100644 index f2244ef3524483b0a2fc70e8f2ba433efd363c01..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/ProducerConsumer.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.openflow.util; - -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Map; -import java.util.Set; - -/** - * The following implement a producer/consumer design pattern in which both - * producers and consumers explicitly employ a centralized registration - * mechanism, and java Interfaces are used as contracts.<br> - */ -public class ProducerConsumer { - - /* - * Class variables - */ - protected static ProducerConsumer singleton; - - /* - * Default constructor - */ - protected ProducerConsumer() { - producerMap = new Hashtable<Class<?>, Set<IProducer>>(); - } - - /* - * Instance variables - */ - - // Interface/IProducer map - protected Map<Class<?>, Set<IProducer>> producerMap; - - /* - * Protected methods - */ - - protected void _registerConsumer(Object consumer, Class<?>[] interfaces, - Set<Class<?>> iSet, - Set<Class<?>> iUniqueSet) { - // *...Process all interfaces...*/ - for (Class<?> iface : interfaces) { - - // *...Protect against repeated interfaces...*/ - if (!iUniqueSet.contains(iface)) { - iUniqueSet.add(iface); - - Set<IProducer> producers = producerMap.get(iface); - - if (producers != null) { - for (IProducer producer : producers) - producer.registerConsumer(iface, consumer); - iSet.add(iface); - } - - // *...Recurse...*/ - _registerConsumer(consumer, iface.getInterfaces(), iSet, - iUniqueSet); - } - } - } - - protected void _registerConsumer(Object consumer, Class<?> clazz, - Set<Class<?>> iSet, - Set<Class<?>> iUniqueSet) { - if (clazz != null) { - // *...Process all interfaces...*/ - _registerConsumer(consumer, clazz.getInterfaces(), iSet, - iUniqueSet); - - // *...Recurse the class hierarchy...*/ - _registerConsumer(consumer, clazz.getSuperclass(), iSet, - iUniqueSet); - } - } - - protected int _deregisterConsumer(Object consumer, - Class<?>[] interfaces, - Set<Class<?>> iUniqueSet) { - int count = 0; - - // *...Process all interfaces...*/ - for (Class<?> iface : interfaces) { - - // *...Protect against repeated interfaces...*/ - if (!iUniqueSet.contains(iface)) { - iUniqueSet.add(iface); - - Set<IProducer> producers = producerMap.get(iface); - - if (producers != null) { - for (IProducer producer : producers) - producer.deregisterConsumer(iface, consumer); - - count++; - } - - // *...Recurse...*/ - count += _deregisterConsumer(consumer, - iface.getInterfaces(), - iUniqueSet); - } - } - - return count; - } - - protected int _deregisterConsumer(Object consumer, Class<?> clazz, - Set<Class<?>> iUniqueSet) { - int count = 0; - - if (clazz != null) { - // *...Process all interfaces...*/ - count += _deregisterConsumer(consumer, clazz.getInterfaces(), - iUniqueSet); - - // *...Recurse the class hierarchy...*/ - count += _deregisterConsumer(consumer, clazz.getSuperclass(), - iUniqueSet); - } - - return count; - } - - /* - * Singleton API - */ - - /** - * @return singleton ProducerConsumer - */ - public static synchronized ProducerConsumer getSingleton() { - if (singleton == null) singleton = new ProducerConsumer(); - - return singleton; - } - - /* - * Producer APIs - */ - - /** - * Producer registration - * - * @param producer - * object that implements IProducer - * @param iface - * interface supported by the producer - * @return whether there was a previously registered producer, or true if - * one or more the arguments were invalid - */ - public boolean registerProducer(IProducer producer, Class<?> iface) { - if (producer != null && iface != null && iface.isInterface()) { - Set<IProducer> producers = producerMap.get(iface); - - if (producers == null) { - producers = new HashSet<IProducer>(); - producerMap.put(iface, producers); - } - - return producers.add(producer); - } else - return true; - } - - /** - * Producer deregistration - * - * @param producer - * object that implements IProducer - * @param iface - * interface supported by the producer - * @return whether the interface/producer pair was removed, or false if one - * or more the arguments were invalid - */ - public boolean deregisterProducer(IProducer producer, Class<?> iface) { - if (producer != null && iface != null && iface.isInterface()) { - Set<IProducer> producers = producerMap.get(iface); - - if (producers != null) return producers.remove(producer); - } - - return false; - } - - /* - * Consumer APIs - */ - - /** - * Consumer registration - * - * @param consumer - * object that implements producer-specific interfaces - * @return set of supported interfaces - */ - public Set<Class<?>> registerConsumer(Object consumer) { - Set<Class<?>> iSet = new HashSet<Class<?>>(); - - if (consumer != null) - _registerConsumer(consumer, - consumer.getClass(), iSet, - new HashSet<Class<?>>()); - - return iSet; - } - - /** - * Consumer deregistration - * - * @param consumer - * object to deregister - * @return number of unregistered interfaces - */ - public int deregisterConsumer(Object consumer) { - if (consumer != null) - return _deregisterConsumer(consumer, consumer.getClass(), - new HashSet<Class<?>>()); - else - return 0; - } - -} diff --git a/src/main/java/org/openflow/util/StringByteSerializer.java b/src/main/java/org/openflow/util/StringByteSerializer.java deleted file mode 100644 index 9287fd20a73464d2483e42a6a4cc60781c45f5bb..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/StringByteSerializer.java +++ /dev/null @@ -1,58 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.Arrays; - -import org.jboss.netty.buffer.ChannelBuffer; - -public class StringByteSerializer { - public static String readFrom(ChannelBuffer data, int length) { - byte[] stringBytes = new byte[length]; - data.readBytes(stringBytes); - // find the first index of 0 - int index = 0; - for (byte b : stringBytes) { - if (0 == b) - break; - ++index; - } - return new String(Arrays.copyOf(stringBytes, index), - Charset.forName("ascii")); - } - - public static void writeTo(ChannelBuffer data, int length, String value) { - try { - byte[] name = value.getBytes("ASCII"); - if (name.length < length) { - data.writeBytes(name); - for (int i = name.length; i < length; ++i) { - data.writeByte((byte) 0); - } - } else { - data.writeBytes(name, 0, length-1); - data.writeByte((byte) 0); - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - - } -} diff --git a/src/main/java/org/openflow/util/U16.java b/src/main/java/org/openflow/util/U16.java deleted file mode 100644 index 0d8917da5fd1c0f18e287d5506904102be196161..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/U16.java +++ /dev/null @@ -1,28 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -public class U16 { - public static int f(short i) { - return (int)i & 0xffff; - } - - public static short t(int l) { - return (short) l; - } -} diff --git a/src/main/java/org/openflow/util/U32.java b/src/main/java/org/openflow/util/U32.java deleted file mode 100644 index 3aab400ebf128079673ad1e98f7b1a1b484bd4aa..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/U32.java +++ /dev/null @@ -1,28 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -public class U32 { - public static long f(int i) { - return (long)i & 0xffffffffL; - } - - public static int t(long l) { - return (int) l; - } -} diff --git a/src/main/java/org/openflow/util/U64.java b/src/main/java/org/openflow/util/U64.java deleted file mode 100644 index c6ae0f7b5c4e7f31521b03c84254502c43542e5d..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/U64.java +++ /dev/null @@ -1,30 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.math.BigInteger; - -public class U64 { - public static BigInteger f(long i) { - return new BigInteger(Long.toBinaryString(i), 2); - } - - public static long t(BigInteger l) { - return l.longValue(); - } -} diff --git a/src/main/java/org/openflow/util/U8.java b/src/main/java/org/openflow/util/U8.java deleted file mode 100644 index 0b575ad24e4d0d0abe433ae49f8725bd96c5fa39..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/U8.java +++ /dev/null @@ -1,28 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -public class U8 { - public static short f(byte i) { - return (short) ((short)i & 0xff); - } - - public static byte t(short l) { - return (byte) l; - } -} diff --git a/src/main/java/org/openflow/util/Unsigned.java b/src/main/java/org/openflow/util/Unsigned.java deleted file mode 100644 index 0754a3f73d751e0296ecd95d6671ec2db7c78dff..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/util/Unsigned.java +++ /dev/null @@ -1,212 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.math.BigInteger; -import java.nio.ByteBuffer; - -/***** - * A util library class for dealing with the lack of unsigned datatypes in Java - * - * @author Rob Sherwood (rob.sherwood@stanford.edu) - * @author David Erickson (daviderickson@cs.stanford.edu) - */ - -public class Unsigned { - /** - * Get an unsigned byte from the current position of the ByteBuffer - * - * @param bb ByteBuffer to get the byte from - * @return an unsigned byte contained in a short - */ - public static short getUnsignedByte(ByteBuffer bb) { - return ((short) (bb.get() & (short) 0xff)); - } - - /** - * Get an unsigned byte from the specified offset in the ByteBuffer - * - * @param bb ByteBuffer to get the byte from - * @param offset the offset to get the byte from - * @return an unsigned byte contained in a short - */ - public static short getUnsignedByte(ByteBuffer bb, int offset) { - return ((short) (bb.get(offset) & (short) 0xff)); - } - - /** - * Put an unsigned byte into the specified ByteBuffer at the current - * position - * - * @param bb ByteBuffer to put the byte into - * @param v the short containing the unsigned byte - */ - public static void putUnsignedByte(ByteBuffer bb, short v) { - bb.put((byte) (v & 0xff)); - } - - /** - * Put an unsigned byte into the specified ByteBuffer at the specified - * offset - * - * @param bb ByteBuffer to put the byte into - * @param v the short containing the unsigned byte - * @param offset the offset to insert the unsigned byte at - */ - public static void putUnsignedByte(ByteBuffer bb, short v, int offset) { - bb.put(offset, (byte) (v & 0xff)); - } - - /** - * Get an unsigned short from the current position of the ByteBuffer - * - * @param bb ByteBuffer to get the byte from - * @return an unsigned short contained in a int - */ - public static int getUnsignedShort(ByteBuffer bb) { - return (bb.getShort() & 0xffff); - } - - /** - * Get an unsigned short from the specified offset in the ByteBuffer - * - * @param bb ByteBuffer to get the short from - * @param offset the offset to get the short from - * @return an unsigned short contained in a int - */ - public static int getUnsignedShort(ByteBuffer bb, int offset) { - return (bb.getShort(offset) & 0xffff); - } - - /** - * Put an unsigned short into the specified ByteBuffer at the current - * position - * - * @param bb ByteBuffer to put the short into - * @param v the int containing the unsigned short - */ - public static void putUnsignedShort(ByteBuffer bb, int v) { - bb.putShort((short) (v & 0xffff)); - } - - /** - * Put an unsigned short into the specified ByteBuffer at the specified - * offset - * - * @param bb ByteBuffer to put the short into - * @param v the int containing the unsigned short - * @param offset the offset to insert the unsigned short at - */ - public static void putUnsignedShort(ByteBuffer bb, int v, int offset) { - bb.putShort(offset, (short) (v & 0xffff)); - } - - /** - * Get an unsigned int from the current position of the ByteBuffer - * - * @param bb ByteBuffer to get the int from - * @return an unsigned int contained in a long - */ - public static long getUnsignedInt(ByteBuffer bb) { - return ((long) bb.getInt() & 0xffffffffL); - } - - /** - * Get an unsigned int from the specified offset in the ByteBuffer - * - * @param bb ByteBuffer to get the int from - * @param offset the offset to get the int from - * @return an unsigned int contained in a long - */ - public static long getUnsignedInt(ByteBuffer bb, int offset) { - return ((long) bb.getInt(offset) & 0xffffffffL); - } - - /** - * Put an unsigned int into the specified ByteBuffer at the current position - * - * @param bb ByteBuffer to put the int into - * @param v the long containing the unsigned int - */ - public static void putUnsignedInt(ByteBuffer bb, long v) { - bb.putInt((int) (v & 0xffffffffL)); - } - - /** - * Put an unsigned int into the specified ByteBuffer at the specified offset - * - * @param bb ByteBuffer to put the int into - * @param v the long containing the unsigned int - * @param offset the offset to insert the unsigned int at - */ - public static void putUnsignedInt(ByteBuffer bb, long v, int offset) { - bb.putInt(offset, (int) (v & 0xffffffffL)); - } - - /** - * Get an unsigned long from the current position of the ByteBuffer - * - * @param bb ByteBuffer to get the long from - * @return an unsigned long contained in a BigInteger - */ - public static BigInteger getUnsignedLong(ByteBuffer bb) { - byte[] v = new byte[8]; - for (int i = 0; i < 8; ++i) { - v[i] = bb.get(i); - } - return new BigInteger(1, v); - } - - /** - * Get an unsigned long from the specified offset in the ByteBuffer - * - * @param bb ByteBuffer to get the long from - * @param offset the offset to get the long from - * @return an unsigned long contained in a BigInteger - */ - public static BigInteger getUnsignedLong(ByteBuffer bb, int offset) { - byte[] v = new byte[8]; - for (int i = 0; i < 8; ++i) { - v[i] = bb.get(offset+i); - } - return new BigInteger(1, v); - } - - /** - * Put an unsigned long into the specified ByteBuffer at the current - * position - * - * @param bb ByteBuffer to put the long into - * @param v the BigInteger containing the unsigned long - */ - public static void putUnsignedLong(ByteBuffer bb, BigInteger v) { - bb.putLong(v.longValue()); - } - - /** - * Put an unsigned long into the specified ByteBuffer at the specified - * offset - * - * @param bb ByteBuffer to put the long into - * @param v the BigInteger containing the unsigned long - * @param offset the offset to insert the unsigned long at - */ - public static void putUnsignedLong(ByteBuffer bb, BigInteger v, int offset) { - bb.putLong(offset, v.longValue()); - } -} diff --git a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java deleted file mode 100644 index 687d5449f2dfdce8a4200f4c70c0f28ac72b67fe..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java +++ /dev/null @@ -1,98 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.vendor.nicira; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Base class for vendor data corresponding to a Nicira vendor extension. - * Nicira vendor data always starts with a 4-byte integer data type value. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFNiciraVendorData implements OFVendorData { - - public static final int NX_VENDOR_ID = 0x00002320; - /** - * The value of the integer data type at the beginning of the vendor data - */ - protected int dataType; - - /** - * Construct empty (i.e. unspecified data type) Nicira vendor data. - */ - public OFNiciraVendorData() { - } - - /** - * Contruct Nicira vendor data with the specified data type - * @param dataType the data type value at the beginning of the vendor data. - */ - public OFNiciraVendorData(int dataType) { - this.dataType = dataType; - } - - /** - * Get the data type value at the beginning of the vendor data - * @return the integer data type value - */ - public int getDataType() { - return dataType; - } - - /** - * Set the data type value - * @param dataType the integer data type value at the beginning of the - * vendor data. - */ - public void setDataType(int dataType) { - this.dataType = dataType; - } - - /** - * Get the length of the vendor data. This implementation will normally - * be the superclass for another class that will override this to return - * the overall vendor data length. This implementation just returns the - * length of the part that includes the 4-byte integer data type value - * at the beginning of the vendor data. - */ - @Override - public int getLength() { - return 4; - } - - /** - * Read the vendor data from the ChannelBuffer - * @param data the channel buffer from which we're deserializing - * @param length the length to the end of the enclosing message - */ - @Override - public void readFrom(ChannelBuffer data, int length) { - dataType = data.readInt(); - } - - /** - * Write the vendor data to the ChannelBuffer - * @param data the channel buffer to which we're serializing - */ - @Override - public void writeTo(ChannelBuffer data) { - data.writeInt(dataType); - } -} diff --git a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java b/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java deleted file mode 100644 index 98f88b242f62a34a3ff4e45b9197f8da58ecc9ec..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.openflow.vendor.nicira; - -import org.openflow.protocol.vendor.OFBasicVendorDataType; -import org.openflow.protocol.vendor.OFBasicVendorId; -import org.openflow.protocol.vendor.OFVendorId; - -public class OFNiciraVendorExtensions { - private static boolean initialized = false; - - public static synchronized void initialize() { - if (initialized) - return; - - // Configure openflowj to be able to parse the role request/reply - // vendor messages. - OFBasicVendorId niciraVendorId = - new OFBasicVendorId(OFNiciraVendorData.NX_VENDOR_ID, 4); - OFVendorId.registerVendorId(niciraVendorId); - OFBasicVendorDataType roleRequestVendorData = - new OFBasicVendorDataType(OFRoleRequestVendorData.NXT_ROLE_REQUEST, - OFRoleRequestVendorData.getInstantiable()); - niciraVendorId.registerVendorDataType(roleRequestVendorData); - OFBasicVendorDataType roleReplyVendorData = - new OFBasicVendorDataType(OFRoleReplyVendorData.NXT_ROLE_REPLY, - OFRoleReplyVendorData.getInstantiable()); - niciraVendorId.registerVendorDataType(roleReplyVendorData); - - initialized = true; - } -} diff --git a/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java deleted file mode 100644 index fa28c71fb5df6b9a083439f01cec911a1c5f0e69..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java +++ /dev/null @@ -1,66 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.vendor.nicira; - -import org.openflow.protocol.Instantiable; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Subclass of OFVendorData representing the vendor data associated with - * a role reply vendor extension. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFRoleReplyVendorData extends OFRoleVendorData { - - protected static Instantiable<OFVendorData> instantiable = - new Instantiable<OFVendorData>() { - public OFVendorData instantiate() { - return new OFRoleReplyVendorData(); - } - }; - - /** - * @return a subclass of Instantiable<OFVendorData> that instantiates - * an instance of OFRoleReplyVendorData. - */ - public static Instantiable<OFVendorData> getInstantiable() { - return instantiable; - } - - /** - * The data type value for a role reply - */ - public static final int NXT_ROLE_REPLY = 11; - - /** - * Construct a role reply vendor data with an unspecified role value. - */ - public OFRoleReplyVendorData() { - super(NXT_ROLE_REPLY); - } - - /** - * Construct a role reply vendor data with the specified role value. - * @param role the role value for the role reply. Should be one of - * NX_ROLE_OTHER, NX_ROLE_MASTER or NX_ROLE_SLAVE. - */ - public OFRoleReplyVendorData(int role) { - super(NXT_ROLE_REPLY, role); - } -} diff --git a/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java deleted file mode 100644 index e7dbe71bda712da557d18678032e9267ba80d308..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java +++ /dev/null @@ -1,66 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.vendor.nicira; - -import org.openflow.protocol.Instantiable; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Subclass of OFVendorData representing the vendor data associated with - * a role request vendor extension. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFRoleRequestVendorData extends OFRoleVendorData { - - protected static Instantiable<OFVendorData> instantiable = - new Instantiable<OFVendorData>() { - public OFVendorData instantiate() { - return new OFRoleRequestVendorData(); - } - }; - - /** - * @return a subclass of Instantiable<OFVendorData> that instantiates - * an instance of OFRoleRequestVendorData. - */ - public static Instantiable<OFVendorData> getInstantiable() { - return instantiable; - } - - /** - * The data type value for a role request - */ - public static final int NXT_ROLE_REQUEST = 10; - - /** - * Construct a role request vendor data with an unspecified role value. - */ - public OFRoleRequestVendorData() { - super(NXT_ROLE_REQUEST); - } - - /** - * Construct a role request vendor data with the specified role value. - * @param role the role value for the role request. Should be one of - * NX_ROLE_OTHER, NX_ROLE_MASTER or NX_ROLE_SLAVE. - */ - public OFRoleRequestVendorData(int role) { - super(NXT_ROLE_REQUEST, role); - } -} diff --git a/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java deleted file mode 100644 index e7c8bf2135b875a74bd14c0ad5393529a3e6e53b..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java +++ /dev/null @@ -1,113 +0,0 @@ -/** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson & Rob Sherwood, Stanford University -* -* 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 org.openflow.vendor.nicira; - -import org.jboss.netty.buffer.ChannelBuffer; - -/** - * Class that represents the vendor data in the role request - * extension implemented by Open vSwitch to support high availability. - * - * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com) - */ -public class OFRoleVendorData extends OFNiciraVendorData { - - /** - * Role value indicating that the controller is in the OTHER role. - */ - public static final int NX_ROLE_OTHER = 0; - - /** - * Role value indicating that the controller is in the MASTER role. - */ - public static final int NX_ROLE_MASTER = 1; - - /** - * Role value indicating that the controller is in the SLAVE role. - */ - public static final int NX_ROLE_SLAVE = 2; - - protected int role; - - /** - * Construct an uninitialized OFRoleVendorData - */ - public OFRoleVendorData() { - super(); - } - - /** - * Construct an OFRoleVendorData with the specified data type - * (i.e. either request or reply) and an unspecified role. - * @param dataType - */ - public OFRoleVendorData(int dataType) { - super(dataType); - } - - /** - * Construct an OFRoleVendorData with the specified data type - * (i.e. either request or reply) and role (i.e. one of of - * master, slave, or other). - * @param dataType either role request or role reply data type - */ - public OFRoleVendorData(int dataType, int role) { - super(dataType); - this.role = role; - } - /** - * @return the role value of the role vendor data - */ - public int getRole() { - return role; - } - - /** - * @param role the role value of the role vendor data - */ - public void setRole(int role) { - this.role = role; - } - - /** - * @return the total length of the role vendor data - */ - @Override - public int getLength() { - return super.getLength() + 4; - } - - /** - * Read the role vendor data from the ChannelBuffer - * @param data the channel buffer from which we're deserializing - * @param length the length to the end of the enclosing message - */ - public void readFrom(ChannelBuffer data, int length) { - super.readFrom(data, length); - role = data.readInt(); - } - - /** - * Write the role vendor data to the ChannelBuffer - * @param data the channel buffer to which we're serializing - */ - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeInt(role); - } -} diff --git a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java deleted file mode 100644 index 9be821f2ace4fb624a0a2314e0b997ec9d086f14..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java +++ /dev/null @@ -1,98 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.vendor.openflow; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Base class for vendor data corresponding to extensions to OpenFlow 1.0. - * Based on org.openflow.vendor.nicira - * - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFOpenFlowVendorData implements OFVendorData { - - public static final int OF_VENDOR_ID = 0x000026e1; - - /** - * The value of the integer data type at the beginning of the vendor data - */ - protected int dataType; - - /** - * Construct empty (i.e. unspecified data type) OpenFlow vendor data. - */ - public OFOpenFlowVendorData() { - } - - /** - * Construct OpenFlow vendor data with the specified data type - * @param dataType the data type value at the beginning of the vendor data. - */ - public OFOpenFlowVendorData(int dataType) { - this.dataType = dataType; - } - - /** - * Get the data type value at the beginning of the vendor data - * @return the integer data type value - */ - public int getDataType() { - return dataType; - } - - /** - * Set the data type value - * @param dataType the integer data type value at the beginning of the - * vendor data. - */ - public void setDataType(int dataType) { - this.dataType = dataType; - } - - /** - * Get the length of the vendor data. This implementation will normally - * be the superclass for another class that will override this to return - * the overall vendor data length. This implementation just returns the - * length of the part that includes the 4-byte integer data type value - * at the beginning of the vendor data. - */ - @Override - public int getLength() { - return 4; - } - - /** - * Read the vendor data from the ChannelBuffer - * @param data the channel buffer from which we're deserializing - * @param length the length to the end of the enclosing message - */ - @Override - public void readFrom(ChannelBuffer data, int length) { - dataType = data.readInt(); - } - - /** - * Write the vendor data to the ChannelBuffer - * @param data the channel buffer to which we're serializing - */ - @Override - public void writeTo(ChannelBuffer data) { - data.writeInt(dataType); - } -} diff --git a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java b/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java deleted file mode 100644 index 3fa10298cbc0ad4307368983cd157e51116e20ef..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java +++ /dev/null @@ -1,47 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.vendor.openflow; - -import org.openflow.protocol.vendor.OFBasicVendorDataType; -import org.openflow.protocol.vendor.OFBasicVendorId; -import org.openflow.protocol.vendor.OFVendorId; - -public class OFOpenFlowVendorExtensions { - private static boolean initialized = false; - - public static synchronized void initialize() { - if (initialized) - return; - - // Configure openflowj to be able to parse the OpenFlow extensions. - OFBasicVendorId openflowVendorId = - new OFBasicVendorId(OFOpenFlowVendorData.OF_VENDOR_ID, 4); - OFVendorId.registerVendorId(openflowVendorId); - - OFBasicVendorDataType queueModifyVendorData = - new OFBasicVendorDataType(OFQueueModifyVendorData.OFP_EXT_QUEUE_MODIFY, - OFQueueModifyVendorData.getInstantiable()); - openflowVendorId.registerVendorDataType(queueModifyVendorData); - - OFBasicVendorDataType queueDeleteVendorData = - new OFBasicVendorDataType(OFQueueDeleteVendorData.OFP_EXT_QUEUE_DELETE, - OFQueueModifyVendorData.getInstantiable()); - openflowVendorId.registerVendorDataType(queueDeleteVendorData); - - initialized = true; - } -} diff --git a/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java deleted file mode 100644 index 4fc52bacb337733d19647ab89f3ee04f553ef018..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java +++ /dev/null @@ -1,52 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.vendor.openflow; - -import org.openflow.protocol.Instantiable; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Class that represents the vendor data in the queue delete request - * - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFQueueDeleteVendorData extends OFQueueVendorData { - - protected static Instantiable<OFVendorData> instantiable = - new Instantiable<OFVendorData>() { - public OFVendorData instantiate() { - return new OFQueueDeleteVendorData(); - } - }; - - /** - * @return a subclass of Instantiable<OFVendorData> that instantiates - * an instance of OFQueueDeleteVendorData. - */ - public static Instantiable<OFVendorData> getInstantiable() { - return instantiable; - } - - /** - * The data type value for a queue delete request - */ - public static final int OFP_EXT_QUEUE_DELETE = 1; - - public OFQueueDeleteVendorData() { - super(OFP_EXT_QUEUE_DELETE); - } -} diff --git a/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java deleted file mode 100644 index 0d2f31b524c22f2e1152735eb5db26d8ae210914..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java +++ /dev/null @@ -1,52 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.vendor.openflow; - -import org.openflow.protocol.Instantiable; -import org.openflow.protocol.vendor.OFVendorData; - -/** - * Class that represents the vendor data in the queue modify request - * - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFQueueModifyVendorData extends OFQueueVendorData { - - protected static Instantiable<OFVendorData> instantiable = - new Instantiable<OFVendorData>() { - public OFVendorData instantiate() { - return new OFQueueModifyVendorData(); - } - }; - - /** - * @return a subclass of Instantiable<OFVendorData> that instantiates - * an instance of OFQueueModifyVendorData. - */ - public static Instantiable<OFVendorData> getInstantiable() { - return instantiable; - } - - /** - * The data type value for a queue modify request - */ - public static final int OFP_EXT_QUEUE_MODIFY = 0; - - public OFQueueModifyVendorData() { - super(OFP_EXT_QUEUE_MODIFY); - } -} diff --git a/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java deleted file mode 100644 index eeae9aace6436f42de2c26151aba1f125e26d83b..0000000000000000000000000000000000000000 --- a/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java +++ /dev/null @@ -1,119 +0,0 @@ -/** -* Copyright 2012, Andrew Ferguson, Brown University -* -* 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 org.openflow.vendor.openflow; - -import java.util.ArrayList; -import java.util.List; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.OFPacketQueue; - -/** - * Class that represents the vendor data in a queue modify or delete request - * - * @author Andrew Ferguson (adf@cs.brown.edu) - */ -public class OFQueueVendorData extends OFOpenFlowVendorData { - public static int MINIMUM_LENGTH = 8; - - protected short portNumber; - protected List<OFPacketQueue> queues = new ArrayList<OFPacketQueue>(); - - public OFQueueVendorData(int dataType) { - super(dataType); - } - - /** - * @return the portNumber - */ - public short getPortNumber() { - return portNumber; - } - - /** - * @param port the port on which the queue is - */ - public void setPortNumber(short portNumber) { - this.portNumber = portNumber; - } - - - /** - * @return the queues - */ - public List<OFPacketQueue> getQueues() { - return queues; - } - - /** - * @param queues the queues to modify or delete - */ - public void setQueues(List<OFPacketQueue> queues) { - this.queues = queues; - } - - /** - * @return the total length of the queue modify or delete msg - */ - @Override - public int getLength() { - int queuesLength = 0; - - for (OFPacketQueue queue : queues) { - queuesLength += queue.getLength(); - } - - return super.getLength() + MINIMUM_LENGTH + queuesLength; - } - - /** - * Read the queue message data from the ChannelBuffer - * @param data the channel buffer from which we're deserializing - * @param length the length to the end of the enclosing message - */ - public void readFrom(ChannelBuffer data, int length) { - super.readFrom(data, length); - portNumber = data.readShort(); - data.readInt(); // pad - data.readShort(); // pad - - int availLength = (length - MINIMUM_LENGTH); - this.queues.clear(); - - while (availLength > 0) { - OFPacketQueue queue = new OFPacketQueue(); - queue.readFrom(data); - queues.add(queue); - availLength -= queue.getLength(); - } - } - - /** - * Write the queue message data to the ChannelBuffer - * @param data the channel buffer to which we're serializing - */ - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(this.portNumber); - data.writeInt(0); // pad - data.writeShort(0); // pad - - for (OFPacketQueue queue : queues) { - queue.writeTo(data); - } - } -} diff --git a/src/main/java/org/sdnplatform/sync/ISyncService.java b/src/main/java/org/sdnplatform/sync/ISyncService.java index 75f3948a8e7b20d669492573b3dc616f8d9c54a7..48feead4a3c378e61147292203db3ccaa6435900 100644 --- a/src/main/java/org/sdnplatform/sync/ISyncService.java +++ b/src/main/java/org/sdnplatform/sync/ISyncService.java @@ -40,6 +40,8 @@ public interface ISyncService extends IFloodlightService { */ UNSYNCHRONIZED } + + public short getLocalNodeId(); /** * Create a store with the given store name and scope diff --git a/src/main/java/org/sdnplatform/sync/internal/SyncTorture.java b/src/main/java/org/sdnplatform/sync/internal/SyncTorture.java deleted file mode 100644 index 74e4ae96648089a28dd38758b817886a01f57f63..0000000000000000000000000000000000000000 --- a/src/main/java/org/sdnplatform/sync/internal/SyncTorture.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.sdnplatform.sync.internal; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.sdnplatform.sync.IStoreClient; -import org.sdnplatform.sync.ISyncService; -import org.sdnplatform.sync.Versioned; -import org.sdnplatform.sync.ISyncService.Scope; -import org.sdnplatform.sync.error.SyncException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -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.debugcounter.IDebugCounterService; - -/** - * A floodlight module that will start up and start doing horrible, - * horrible things to the sync service. - * @author readams - */ -public class SyncTorture implements IFloodlightModule { - protected static final Logger logger = - LoggerFactory.getLogger(SyncTorture.class); - - private static final String SYNC_STORE_NAME = - SyncTorture.class.getCanonicalName() + ".torture"; - - ISyncService syncService; - IDebugCounterService debugCounter; - - int numWorkers = 2; - int keysPerWorker = 1024*1024; - int iterations = 0; - int delay = 0; - - @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(ISyncService.class); - l.add(IDebugCounterService.class); - - return l; - } - - @Override - public void init(FloodlightModuleContext context) - throws FloodlightModuleException { - syncService = context.getServiceImpl(ISyncService.class); - debugCounter = context.getServiceImpl(IDebugCounterService.class); - - try { - syncService.registerStore(SYNC_STORE_NAME, Scope.GLOBAL); - } catch (SyncException e) { - throw new FloodlightModuleException(e); - } - - Map<String,String> config = context.getConfigParams(this); - if (config.containsKey("numWorkers")) { - numWorkers = Integer.parseInt(config.get("numWorkers")); - } - if (config.containsKey("keysPerWorker")) { - keysPerWorker = Integer.parseInt(config.get("keysPerWorker")); - } - if (config.containsKey("iterations")) { - iterations = Integer.parseInt(config.get("iterations")); - } - if (config.containsKey("delay")) { - delay = Integer.parseInt(config.get("delay")); - } - } - - @Override - public void startUp(FloodlightModuleContext context) - throws FloodlightModuleException { - try { - final IStoreClient<String, TortureValue> storeClient = - syncService.getStoreClient(SYNC_STORE_NAME, - String.class, - TortureValue.class); - for (int i = 0; i < numWorkers; i++) { - Thread thread = new Thread(new TortureWorker(storeClient, i), - "Torture-" + i); - thread.setPriority(Thread.MIN_PRIORITY); - thread.start(); - } - } catch (Exception e) { - throw new FloodlightModuleException(e); - } - } - - protected static class TortureValue { - private String string; - private int integer; - private boolean bool; - - public TortureValue() { - super(); - } - - public TortureValue(String string, int integer, boolean bool) { - super(); - this.string = string; - this.integer = integer; - this.bool = bool; - } - - public String getString() { - return string; - } - public void setString(String string) { - this.string = string; - } - public int getInteger() { - return integer; - } - public void setInteger(int integer) { - this.integer = integer; - } - public boolean isBool() { - return bool; - } - public void setBool(boolean bool) { - this.bool = bool; - } - } - - protected class TortureWorker implements Runnable { - final IStoreClient<String, TortureValue> storeClient; - final int workerId; - final List<TortureValue> values; - - public TortureWorker(IStoreClient<String, TortureValue> storeClient, - int workerId) { - super(); - this.storeClient = storeClient; - this.workerId = workerId; - values = new ArrayList<TortureValue>(); - for (int i = 0; i < keysPerWorker; i++) { - values.add(new TortureValue(workerId+":"+i, 0, true)); - } - } - - @Override - public void run() { - if (delay > 0) { - try { - Thread.sleep(delay); - } catch (InterruptedException e) { } - } - int i = 0; - while (iterations == 0 || i++ < iterations) { - long start = System.currentTimeMillis(); - try { - for (TortureValue v : values) { - Versioned<TortureValue> vv = - storeClient.get(v.getString()); - v.setInteger(v.getInteger() + 1); - v.setBool(!v.isBool()); - vv.setValue(v); - storeClient.put(v.getString(), vv); - } - } catch (Exception e) { - logger.error("Error in worker: ", e); - } - long iterend = System.currentTimeMillis(); - debugCounter.flushCounters(); - logger.info("Completed iteration of {} values in {}ms" + - " ({}/s)", - new Object[]{values.size(), (iterend-start), - 1000*values.size()/(iterend-start)}); - } - - } - } -} diff --git a/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java b/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java index 27addf7fe1ff448d154af8222d561604a31e86b3..416f4ebaacddf5455a40e404ceefe251526a2617 100644 --- a/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java +++ b/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java @@ -15,6 +15,7 @@ import org.sdnplatform.sync.error.SyncException; * @author readams */ public class ClusterConfig { + public static final short NODE_ID_UNCONFIGURED = Short.MAX_VALUE; private HashMap<Short, Node> allNodes = new HashMap<Short, Node>(); diff --git a/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java b/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java index 5a9473562e4d226fb7e8f5f22e805074bcd90129..733f03af894c09f3e310ed84f7d5feada55a41b0 100644 --- a/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java +++ b/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java @@ -4,7 +4,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.util.HexString; /** * A byte array container that provides an equals and hashCode pair based on the diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java index b06589a30a6493bd22d7da347a7bab7e6d4fd642..e5b3347805af7289e2e8abe90234f38df54b0ee8 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java @@ -95,7 +95,7 @@ import org.sdnplatform.sync.test.MockSyncService; public class ControllerTest extends FloodlightTestCase { - private Controller controller; + private OLD__Controller controller; private MockThreadPoolService tp; private MockSyncService syncService; private IStoreClient<Long, SwitchSyncRepresentation> storeClient; @@ -115,7 +115,7 @@ public class ControllerTest extends FloodlightTestCase { FloodlightProvider cm = new FloodlightProvider(); fmc.addConfigParam(cm, "role", role.toString()); - controller = (Controller)cm.getServiceImpls().get(IFloodlightProviderService.class); + controller = (OLD__Controller)cm.getServiceImpls().get(IFloodlightProviderService.class); fmc.addService(IFloodlightProviderService.class, controller); MemoryStorageSource memstorage = new MemoryStorageSource(); @@ -165,7 +165,7 @@ public class ControllerTest extends FloodlightTestCase { cm.startUp(fmc); storeClient = - syncService.getStoreClient(Controller.SWITCH_SYNC_STORE_NAME, + syncService.getStoreClient(OLD__Controller.SWITCH_SYNC_STORE_NAME, Long.class, SwitchSyncRepresentation.class); @@ -204,7 +204,7 @@ public class ControllerTest extends FloodlightTestCase { controller.isUpdateQueueEmptyForTesting()); } - public Controller getController() { + public OLD__Controller getController() { return controller; } @@ -2048,11 +2048,11 @@ public class ControllerTest extends FloodlightTestCase { private Map<String,Object> getFakeControllerIPRow(String id, String controllerId, String type, int number, String discoveredIP ) { HashMap<String, Object> row = new HashMap<String,Object>(); - row.put(Controller.CONTROLLER_INTERFACE_ID, id); - row.put(Controller.CONTROLLER_INTERFACE_CONTROLLER_ID, controllerId); - row.put(Controller.CONTROLLER_INTERFACE_TYPE, type); - row.put(Controller.CONTROLLER_INTERFACE_NUMBER, number); - row.put(Controller.CONTROLLER_INTERFACE_DISCOVERED_IP, discoveredIP); + row.put(OLD__Controller.CONTROLLER_INTERFACE_ID, id); + row.put(OLD__Controller.CONTROLLER_INTERFACE_CONTROLLER_ID, controllerId); + row.put(OLD__Controller.CONTROLLER_INTERFACE_TYPE, type); + row.put(OLD__Controller.CONTROLLER_INTERFACE_NUMBER, number); + row.put(OLD__Controller.CONTROLLER_INTERFACE_DISCOVERED_IP, discoveredIP); return row; } @@ -2139,7 +2139,7 @@ public class ControllerTest extends FloodlightTestCase { synchronized(listener) { // Insert a first entry controller.getStorageSourceService() - .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1")); expectedCurMap.clear(); expectedAddedMap.clear(); @@ -2151,7 +2151,7 @@ public class ControllerTest extends FloodlightTestCase { // Add an interface that we want to ignore. controller.getStorageSourceService() - .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2")); // TODO: do a different check. This call will have to wait for the timeout controller.processUpdateQueueForTesting(); @@ -2160,7 +2160,7 @@ public class ControllerTest extends FloodlightTestCase { // Add another entry controller.getStorageSourceService() - .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2")); expectedCurMap.clear(); expectedAddedMap.clear(); @@ -2174,7 +2174,7 @@ public class ControllerTest extends FloodlightTestCase { // Update an entry controller.getStorageSourceService() - .updateRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .updateRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, "row3", getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.3")); expectedCurMap.clear(); expectedAddedMap.clear(); @@ -2188,7 +2188,7 @@ public class ControllerTest extends FloodlightTestCase { // Delete an entry controller.getStorageSourceService() - .deleteRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, "row3"); + .deleteRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, "row3"); expectedCurMap.clear(); expectedAddedMap.clear(); expectedRemovedMap.clear(); @@ -2204,13 +2204,13 @@ public class ControllerTest extends FloodlightTestCase { HashMap<String,String> expectedCurMap = new HashMap<String, String>(); controller.getStorageSourceService() - .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1")); controller.getStorageSourceService() - .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2")); controller.getStorageSourceService() - .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, + .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2")); expectedCurMap.put("c1", "1.1.1.1"); expectedCurMap.put("c2", "2.2.2.2"); diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java index ed01868b0035eeae062f8f8f17afa2930a3c5ed2..bc4490e73aa34e96c0dc716783999a8e8f59a54d 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java @@ -66,7 +66,7 @@ import static org.junit.Assert.*; public class OFChannelHandlerTest { private static final short CORE_PRIORITY = 4242; private static final short ACCESS_PRIORITY = 42; - private Controller controller; + private OLD__Controller controller; private IThreadPoolService threadPool; private IDebugCounterService debugCounterService; private OFChannelHandler handler; @@ -110,7 +110,7 @@ public class OFChannelHandlerTest { @Before public void setUp() throws Exception { - controller = createMock(Controller.class); + controller = createMock(OLD__Controller.class); threadPool = createMock(IThreadPoolService.class); ctx = createMock(ChannelHandlerContext.class); channelStateEvent = createMock(ChannelStateEvent.class); @@ -125,8 +125,8 @@ public class OFChannelHandlerTest { // TODO: should mock IDebugCounterService and make sure // the expected counters are updated. debugCounterService = new DebugCounter(); - Controller.Counters counters = - new Controller.Counters(); + OLD__Controller.Counters counters = + new OLD__Controller.Counters(); counters.createCounters(debugCounterService); expect(controller.getCounters()).andReturn(counters).anyTimes(); replay(controller); @@ -442,7 +442,7 @@ public class OFChannelHandlerTest { Iterator<IResultSet> it = null; if (cfg.isPresent) { - storageResultSet.getBoolean(Controller.SWITCH_CONFIG_CORE_SWITCH); + storageResultSet.getBoolean(OLD__Controller.SWITCH_CONFIG_CORE_SWITCH); expectLastCall().andReturn(cfg.isCoreSwitch).atLeastOnce(); it = Collections.singletonList(storageResultSet).iterator(); } else { @@ -452,7 +452,7 @@ public class OFChannelHandlerTest { storageResultSet.close(); expectLastCall().atLeastOnce(); expect(storageResultSet.iterator()).andReturn(it).atLeastOnce(); - storageSource.getRow(Controller.SWITCH_CONFIG_TABLE_NAME, cfg.dpid); + storageSource.getRow(OLD__Controller.SWITCH_CONFIG_TABLE_NAME, cfg.dpid); expectLastCall().andReturn(storageResultSet).atLeastOnce(); replay(storageResultSet, storageSource); } diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java index c3cc59ed3c6cb5d50b2abbf047bd54d5a221c883..1e5e4643e894e868ebffff36c7cdad986d5e41c4 100644 --- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java +++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java @@ -30,7 +30,7 @@ import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.IFloodlightProviderService.Role; import net.floodlightcontroller.core.ImmutablePort; -import net.floodlightcontroller.core.internal.Controller; +import net.floodlightcontroller.core.internal.OLD__Controller; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.threadpool.IThreadPoolService; @@ -357,7 +357,7 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { } @Override - public void setFloodlightProvider(Controller controller) { + public void setFloodlightProvider(OLD__Controller controller) { fail("Unexpected method call"); // TODO Auto-generated method stub diff --git a/src/test/java/org/openflow/protocol/BasicFactoryTest.java b/src/test/java/org/openflow/protocol/BasicFactoryTest.java deleted file mode 100644 index 350d4be39c3f1148c7a6c4191085bbe8bb9132a5..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/BasicFactoryTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import static org.junit.Assert.assertArrayEquals; - -import java.util.List; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.action.MockVendorAction; -import org.openflow.protocol.action.MockVendorActionFactory; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionVendorGeneric; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.MessageParseException; -import org.openflow.protocol.factory.OFVendorActionRegistry; -import org.openflow.util.U16; - -public class BasicFactoryTest extends TestCase { - - public void testCreateAndParse() throws MessageParseException { - BasicFactory factory = BasicFactory.getInstance(); - OFMessage m = factory.getMessage(OFType.HELLO); - m.setVersion((byte) 1); - m.setType(OFType.ECHO_REQUEST); - m.setLength(U16.t(8)); - m.setXid(0xdeadbeef); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - ChannelBuffer bb2 = ChannelBuffers.dynamicBuffer(); - m.writeTo(bb); - bb2.writeBytes(bb, bb.readableBytes()-1); - TestCase.assertNull(factory.parseMessage(bb2)); - bb2.writeByte(bb.readByte()); - List<OFMessage> message = factory.parseMessage(bb2); - TestCase.assertNotNull(message); - TestCase.assertEquals(message.size(), 1); - TestCase.assertTrue(message.get(0).getType() == OFType.ECHO_REQUEST); - } - - public void testInvalidMsgParse() throws MessageParseException { - BasicFactory factory = BasicFactory.getInstance(); - OFMessage m = factory.getMessage(OFType.HELLO); - m.setVersion((byte) 1); - m.setType(OFType.ECHO_REQUEST); - m.setLength(U16.t(16)); - m.setXid(0xdeadbeef); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - m.writeTo(bb); - List<OFMessage> message = factory.parseMessage(bb); - TestCase.assertNull(message); - } - - public void testCurrouptedMsgParse() throws MessageParseException { - BasicFactory factory = BasicFactory.getInstance(); - OFMessage m = factory.getMessage(OFType.HELLO); - m.setVersion((byte) 1); - m.setType(OFType.ERROR); - m.setLength(U16.t(8)); - m.setXid(0xdeadbeef); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - m.writeTo(bb); - try { - factory.parseMessage(bb); - } - catch(Exception e) { - TestCase.assertEquals(MessageParseException.class, e.getClass()); - } - } - - public void testCustomVendorAction() throws MessageParseException { - BasicFactory factory = BasicFactory.getInstance(); - OFVendorActionRegistry.getInstance().register( - MockVendorAction.VENDOR_ID, new MockVendorActionFactory()); - - - byte[] deadBeefMessage = { - (byte) 0xff, (byte) 0xff, // action vendor - 0x00, 0x10, // length - (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte)0xef, // deadbeaf - 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08 // pad - }; - - ChannelBuffer buf = ChannelBuffers.copiedBuffer(deadBeefMessage); - - List<OFAction> actions = factory.parseActions(buf,deadBeefMessage.length); - assertEquals(1, actions.size()); - OFAction ofAction = actions.get(0); - assertTrue("Action should be MockVendorAction, but is "+ofAction.getClass(), ofAction instanceof MockVendorAction); - assertArrayEquals( new byte[] { 1,2,3,4,5,6,7,8}, ((MockVendorAction)ofAction).getMockData()); - - - } - - public void testGenericVendorAction() throws MessageParseException { - byte[] nonDeadBeefMessage = { - (byte) 0xff, (byte) 0xff, // action vendor - 0x00, 0x10, // length - (byte) 0x7e, (byte) 0xe7, (byte) 0xbe, (byte)0xef, // deadbeaf - 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x08 // pad - }; - - BasicFactory factory = BasicFactory.getInstance(); - OFVendorActionRegistry.getInstance().register( - MockVendorAction.VENDOR_ID, new MockVendorActionFactory()); - - ChannelBuffer buf = ChannelBuffers.copiedBuffer(nonDeadBeefMessage); - - List<OFAction> actions = factory.parseActions(buf,nonDeadBeefMessage.length); - assertEquals(1, actions.size()); - OFAction ofAction = actions.get(0); - assertTrue("Action should be OFActionVendorGeneric, but is "+ofAction.getClass(), ofAction instanceof OFActionVendorGeneric); - } - -} diff --git a/src/test/java/org/openflow/protocol/OFActionTypeTest.java b/src/test/java/org/openflow/protocol/OFActionTypeTest.java deleted file mode 100644 index ed8386cd745dd7db691e334d6bd64fec81e67745..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFActionTypeTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import org.junit.Test; -import org.openflow.protocol.action.OFActionType; - -import junit.framework.TestCase; - - -public class OFActionTypeTest extends TestCase { - @Test - public void testMapping() throws Exception { - TestCase.assertEquals(OFActionType.OUTPUT, - OFActionType.valueOf((short) 0)); - TestCase.assertEquals(OFActionType.OPAQUE_ENQUEUE, - OFActionType.valueOf((short) 11)); - TestCase.assertEquals(OFActionType.VENDOR, - OFActionType.valueOf((short) 0xffff)); - } -} diff --git a/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java b/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java deleted file mode 100644 index 7e447bb071bf477448823d085db1d6a9e7e72701..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - -public class OFBarrierReplyTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFBarrierReply msg = (OFBarrierReply) messageFactory - .getMessage(OFType.BARRIER_REPLY); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.BARRIER_REPLY, msg.getType()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java b/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java deleted file mode 100644 index 3aa9cb4a789f6ea2202878a6d92da898d76a4490..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - -public class OFBarrierRequestTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFBarrierRequest msg = (OFBarrierRequest) messageFactory - .getMessage(OFType.BARRIER_REQUEST); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.BARRIER_REQUEST, msg.getType()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFErrorTest.java b/src/test/java/org/openflow/protocol/OFErrorTest.java deleted file mode 100644 index f4a57269826d81cf17b47b547e4b7588afeb873f..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFErrorTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.List; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.OFError.OFErrorType; -import org.openflow.protocol.OFError.OFHelloFailedCode; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.MessageParseException; -import org.openflow.protocol.factory.OFMessageFactory; -import org.openflow.util.OFTestCase; - -public class OFErrorTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFError msg = (OFError) messageFactory.getMessage(OFType.ERROR); - msg.setMessageFactory(messageFactory); - msg.setErrorType(OFErrorType.OFPET_HELLO_FAILED.getValue()); - msg.setErrorCode((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE - .ordinal()); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFErrorType.OFPET_HELLO_FAILED.getValue(), - msg.getErrorType()); - TestCase.assertEquals((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE - .ordinal(), msg.getErrorType()); - TestCase.assertNull(msg.getOffendingMsg()); - - msg.setOffendingMsg(new OFHello()); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFErrorType.OFPET_HELLO_FAILED.getValue(), - msg.getErrorType()); - TestCase.assertEquals((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE - .ordinal(), msg.getErrorType()); - TestCase.assertNotNull(msg.getOffendingMsg()); - TestCase.assertEquals(OFHello.MINIMUM_LENGTH, - msg.getOffendingMsg().length); - } - - public void testGarbageAtEnd() throws MessageParseException { - // This is a OFError msg (12 bytes), that encaps a OFVendor msg (24 - // bytes) - // AND some zeros at the end (40 bytes) for a total of 76 bytes - // THIS is what an NEC sends in reply to Nox's VENDOR request - byte[] oferrorRaw = { 0x01, 0x01, 0x00, 0x4c, 0x00, 0x00, 0x10, - (byte) 0xcc, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x00, 0x18, - 0x00, 0x00, 0x10, (byte) 0xcc, 0x00, 0x00, 0x23, 0x20, 0x00, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 }; - OFMessageFactory factory = BasicFactory.getInstance(); - ChannelBuffer oferrorBuf = - ChannelBuffers.wrappedBuffer(oferrorRaw); - List<OFMessage> msg = factory.parseMessage(oferrorBuf); - TestCase.assertNotNull(msg); - TestCase.assertEquals(msg.size(), 1); - TestCase.assertEquals(76, msg.get(0).getLengthU()); - ChannelBuffer out = ChannelBuffers.dynamicBuffer(); - msg.get(0).writeTo(out); - TestCase.assertEquals(76, out.readableBytes()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java b/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java deleted file mode 100644 index 62e491a995a3f232be6027043144f6544d70e1d8..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - - -public class OFFeaturesReplyTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFFeaturesReply ofr = (OFFeaturesReply) messageFactory - .getMessage(OFType.FEATURES_REPLY); - List<OFPhysicalPort> ports = new ArrayList<OFPhysicalPort>(); - OFPhysicalPort port = new OFPhysicalPort(); - port.setHardwareAddress(new byte[6]); - port.setName("eth0"); - ports.add(port); - ofr.setPorts(ports); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - ofr.writeTo(bb); - ofr.readFrom(bb); - TestCase.assertEquals(1, ofr.getPorts().size()); - TestCase.assertEquals("eth0", ofr.getPorts().get(0).getName()); - - // test a 15 character name - ofr.getPorts().get(0).setName("012345678901234"); - bb.clear(); - ofr.writeTo(bb); - ofr.readFrom(bb); - TestCase.assertEquals("012345678901234", ofr.getPorts().get(0).getName()); - - // test a 16 character name getting truncated - ofr.getPorts().get(0).setName("0123456789012345"); - bb.clear(); - ofr.writeTo(bb); - ofr.readFrom(bb); - TestCase.assertEquals("012345678901234", ofr.getPorts().get(0).getName()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java b/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java deleted file mode 100644 index 11746e72411a663170e7ebbf4a8571fb68f8b13f..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.OFFlowRemoved.OFFlowRemovedReason; -import org.openflow.util.OFTestCase; - -public class OFFlowRemovedTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFFlowRemoved msg = (OFFlowRemoved) messageFactory - .getMessage(OFType.FLOW_REMOVED); - msg.setMatch(new OFMatch()); - byte[] hwAddr = new byte[6]; - msg.getMatch().setDataLayerDestination(hwAddr); - msg.getMatch().setDataLayerSource(hwAddr); - msg.setReason(OFFlowRemovedReason.OFPRR_DELETE); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.FLOW_REMOVED, msg.getType()); - TestCase.assertEquals(OFFlowRemovedReason.OFPRR_DELETE, msg.getReason()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java b/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java deleted file mode 100644 index c1f1f671a6767bb11dc3993c65fc21845d0820ab..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - -public class OFGetConfigReplyTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFSetConfig msg = (OFSetConfig) messageFactory - .getMessage(OFType.SET_CONFIG); - msg.setFlags((short) 1); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.SET_CONFIG, msg.getType()); - TestCase.assertEquals((short)1, msg.getFlags()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java b/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java deleted file mode 100644 index 94d9036e68dd1e0b6573148e068fb4380f9946ef..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - -public class OFGetConfigRequestTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFGetConfigRequest msg = (OFGetConfigRequest) messageFactory - .getMessage(OFType.GET_CONFIG_REQUEST); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.GET_CONFIG_REQUEST, msg.getType()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFMatchTest.java b/src/test/java/org/openflow/protocol/OFMatchTest.java deleted file mode 100644 index fd7863acc12d49e89054ced08111def1c5559b6d..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFMatchTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -public class OFMatchTest extends TestCase { - public void testFromString() { - OFMatch correct = new OFMatch(); - OFMatch tester = new OFMatch(); - - // Various combinations of "all"/"any" - tester.fromString("OFMatch[]"); - // correct is already wildcarded - TestCase.assertEquals(correct, tester); - tester.fromString("all"); - TestCase.assertEquals(correct, tester); - tester.fromString("ANY"); - TestCase.assertEquals(correct, tester); - tester.fromString(""); - TestCase.assertEquals(correct, tester); - tester.fromString("[]"); - TestCase.assertEquals(correct, tester); - - // ip_src - correct.setWildcards(~OFMatch.OFPFW_NW_SRC_MASK); - correct.setNetworkSource(0x01010203); - tester.fromString("nw_src=1.1.2.3"); - TestCase.assertEquals(correct.getNetworkSourceMaskLen(), tester - .getNetworkSourceMaskLen()); - TestCase.assertEquals(correct, tester); - tester.fromString("IP_sRc=1.1.2.3"); - TestCase.assertEquals(correct.getNetworkSourceMaskLen(), tester - .getNetworkSourceMaskLen()); - TestCase.assertEquals(correct, tester); - - // 0xVlan - correct = new OFMatch(); - correct.setDataLayerVirtualLan((short)65535); - correct.setWildcards(~OFMatch.OFPFW_DL_VLAN); - tester = new OFMatch(); - tester.fromString("dl_vlan=0xffff"); - TestCase.assertEquals(correct, tester); - } - - public void testToString() { - OFMatch match = new OFMatch(); - match.fromString("nw_dst=3.4.5.6/8"); - TestCase.assertEquals(8, match.getNetworkDestinationMaskLen()); - String correct = "OFMatch[nw_dst=3.0.0.0/8]"; - String tester = match.toString(); - - TestCase.assertEquals(correct, tester); - tester = "OFMatch[dl_type=35020]"; - correct = "OFMatch[dl_type=0x88cc]"; - match = new OFMatch(); - match.fromString(tester); - TestCase.assertEquals(correct, match.toString()); - OFMatch match2 = new OFMatch(); - match2.fromString(correct); - TestCase.assertEquals(match, match2); - } - - public void testClone() { - OFMatch match1 = new OFMatch(); - OFMatch match2 = match1.clone(); - TestCase.assertEquals(match1, match2); - match2.setNetworkProtocol((byte) 4); - match2.setWildcards(match2.getWildcards() & ~OFMatch.OFPFW_NW_PROTO); - TestCase.assertNotSame(match1, match2); - } - - public void testIpToString() { - String test = OFMatch.ipToString(-1); - TestCase.assertEquals("255.255.255.255", test); - } -} diff --git a/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java b/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java deleted file mode 100644 index 60a9e732b05ba2d03ccbf1c4b9793634cafdeb8a..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java +++ /dev/null @@ -1,31 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -public class OFMessageContextStoreTest extends TestCase { - public void testStoreAndGet() { - OFMessage msg = new OFMessage(); - OFMessageContextStore<String> store = new OFMessageContextStore<String>(msg, this.getName()); - String key = "mykey"; - String value = "myvalue"; - store.put(key, value); - TestCase.assertEquals(value, store.get(key)); - } -} diff --git a/src/test/java/org/openflow/protocol/OFPacketOutTest.java b/src/test/java/org/openflow/protocol/OFPacketOutTest.java deleted file mode 100644 index 55b54552fe03b279f20f076dd8857994dded0e09..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFPacketOutTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.openflow.protocol; - -import org.junit.Test; - -public class OFPacketOutTest { - - @Test(expected = IllegalArgumentException.class) - public void testBothBufferIdAndPayloadSet() { - OFPacketOut packetOut = new OFPacketOut(); - packetOut.setBufferId(12); - packetOut.setPacketData(new byte[] { 1, 2, 3 }); - } - - @Test - public void testOnlyBufferIdSet() { - OFPacketOut packetOut = new OFPacketOut(); - packetOut.setBufferId(12); - packetOut.setPacketData(null); - packetOut.setPacketData(new byte[] {}); - packetOut.validate(); - } - - @Test(expected = IllegalStateException.class) - public void testNeitherBufferIdNorPayloadSet() { - OFPacketOut packetOut = new OFPacketOut(); - packetOut.setBufferId(OFPacketOut.BUFFER_ID_NONE); - packetOut.setPacketData(null); - packetOut.validate(); - } - - @Test(expected = IllegalStateException.class) - public void testNeitherBufferIdNorPayloadSet2() { - OFPacketOut packetOut = new OFPacketOut(); - packetOut.setBufferId(OFPacketOut.BUFFER_ID_NONE); - packetOut.setPacketData(new byte[] {}); - packetOut.validate(); - } - - @Test(expected = IllegalStateException.class) - public void testNeitherBufferIdNorPayloadSet3() { - OFPacketOut packetOut = new OFPacketOut(); - packetOut.validate(); - } - -} diff --git a/src/test/java/org/openflow/protocol/OFPortConfigTest.java b/src/test/java/org/openflow/protocol/OFPortConfigTest.java deleted file mode 100644 index 9b115ebc40027a15bfe2f1589d39855bc1051ba2..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFPortConfigTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - -public class OFPortConfigTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFPortMod msg = (OFPortMod) messageFactory - .getMessage(OFType.PORT_MOD); - msg.setHardwareAddress(new byte[6]); - msg.portNumber = 1; - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.PORT_MOD, msg.getType()); - TestCase.assertEquals(1, msg.getPortNumber()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFPortStatusTest.java b/src/test/java/org/openflow/protocol/OFPortStatusTest.java deleted file mode 100644 index 4fab64e03568194784f6b7eaf4518ece9a5017c0..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFPortStatusTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.OFPortStatus.OFPortReason; -import org.openflow.util.OFTestCase; - -public class OFPortStatusTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFPortStatus msg = (OFPortStatus) messageFactory - .getMessage(OFType.PORT_STATUS); - msg.setDesc(new OFPhysicalPort()); - msg.getDesc().setHardwareAddress(new byte[6]); - msg.getDesc().setName("eth0"); - msg.setReason((byte) OFPortReason.OFPPR_ADD.ordinal()); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.PORT_STATUS, msg.getType()); - TestCase.assertEquals((byte) OFPortReason.OFPPR_ADD.ordinal(), msg - .getReason()); - TestCase.assertNotNull(msg.getDesc()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFSetConfigTest.java b/src/test/java/org/openflow/protocol/OFSetConfigTest.java deleted file mode 100644 index 2a9e86f7720fb44baf87acaf487d901a2218e026..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFSetConfigTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.util.OFTestCase; - -public class OFSetConfigTest extends OFTestCase { - public void testWriteRead() throws Exception { - OFGetConfigReply msg = (OFGetConfigReply) messageFactory - .getMessage(OFType.GET_CONFIG_REPLY); - msg.setFlags((short) 1); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(OFType.GET_CONFIG_REPLY, msg.getType()); - TestCase.assertEquals((short)1, msg.getFlags()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java b/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java deleted file mode 100644 index 1885cae7b3d4731ccae5bfbe4fdb295951b1a760..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.List; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.OFMessageFactory; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.util.OFTestCase; - -public class OFStatisticsReplyTest extends OFTestCase { - public void testOFFlowStatisticsReply() throws Exception { - byte[] packet = new byte[] { 0x01, 0x11, 0x01, 0x2c, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, (byte) 0xff, - (byte) 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, (byte) 0xa6, - (byte) 0xa6, 0x00, (byte) 0xff, (byte) 0xff, 0x00, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - (byte) 0xc4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x08, 0x06, - 0x00, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3b, 0x2f, (byte) 0xfa, 0x40, (byte) 0xff, (byte) 0xff, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, (byte) 0xff, (byte) 0xff, 0x00, 0x62, 0x08, - 0x00, 0x00, 0x01, 0x62, 0x37, 0x0a, 0x00, 0x00, 0x02, 0x0a, - 0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3a, (byte) 0xc5, 0x2a, (byte) 0x80, (byte) 0xff, - (byte) 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xc4, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x02, 0x00, 0x00 }; - - OFMessageFactory factory = BasicFactory.getInstance(); - ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet); - List<OFMessage> msg = factory.parseMessage(packetBuf); - TestCase.assertNotNull(msg); - TestCase.assertEquals(msg.size(), 1); - TestCase.assertTrue(msg.get(0) instanceof OFStatisticsReply); - OFStatisticsReply sr = (OFStatisticsReply) msg.get(0); - TestCase.assertEquals(OFStatisticsType.FLOW, sr.getStatisticType()); - TestCase.assertEquals(3, sr.getStatistics().size()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java b/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java deleted file mode 100644 index fceb8955eb755a12bb03c68bd1102513874b06ab..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.List; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.OFMessageFactory; -import org.openflow.protocol.statistics.OFFlowStatisticsRequest; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.openflow.protocol.statistics.OFVendorStatistics; -import org.openflow.util.OFTestCase; - -public class OFStatisticsRequestTest extends OFTestCase { - public void testOFFlowStatisticsRequest() throws Exception { - byte[] packet = new byte[] { 0x01, 0x10, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x01, 0x00, 0x00, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - (byte) 0xff, 0x00, (byte) 0xff, (byte) 0xff }; - - OFMessageFactory factory = BasicFactory.getInstance(); - ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet); - List<OFMessage> msg = factory.parseMessage(packetBuf); - TestCase.assertNotNull(msg); - TestCase.assertEquals(msg.size(), 1); - TestCase.assertTrue(msg.get(0) instanceof OFStatisticsRequest); - OFStatisticsRequest sr = (OFStatisticsRequest) msg.get(0); - TestCase.assertEquals(OFStatisticsType.FLOW, sr.getStatisticType()); - TestCase.assertEquals(1, sr.getStatistics().size()); - TestCase.assertTrue(sr.getStatistics().get(0) instanceof OFFlowStatisticsRequest); - } - - public void testOFStatisticsRequestVendor() throws Exception { - byte[] packet = new byte[] { 0x01, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x63, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20, - (byte) 0xe0, 0x00, 0x11, 0x00, 0x0c, 0x29, (byte) 0xc5, - (byte) 0x95, 0x57, 0x02, 0x25, 0x5c, (byte) 0xca, 0x00, 0x02, - (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x50, 0x04, - 0x00, 0x00, 0x00, 0x00, (byte) 0xff, 0x00, 0x00, 0x00, - (byte) 0xff, (byte) 0xff, 0x4e, 0x20 }; - - OFMessageFactory factory = BasicFactory.getInstance(); - ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet); - List<OFMessage> msg = factory.parseMessage(packetBuf); - TestCase.assertNotNull(msg); - TestCase.assertEquals(msg.size(), 1); - TestCase.assertTrue(msg.get(0) instanceof OFStatisticsRequest); - OFStatisticsRequest sr = (OFStatisticsRequest) msg.get(0); - TestCase.assertEquals(OFStatisticsType.VENDOR, sr.getStatisticType()); - TestCase.assertEquals(1, sr.getStatistics().size()); - TestCase.assertTrue(sr.getStatistics().get(0) instanceof OFVendorStatistics); - TestCase.assertEquals(68, ((OFVendorStatistics)sr.getStatistics().get(0)).getLength()); - } -} diff --git a/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java b/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java deleted file mode 100644 index d44ef7f8e4553f3556efb0bb52ad193578c07bbf..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import junit.framework.TestCase; - -import org.junit.Test; -import org.openflow.protocol.statistics.OFStatisticsType; - - -public class OFStatisticsTypeTest extends TestCase { - @Test - public void testMapping() throws Exception { - TestCase.assertEquals(OFStatisticsType.DESC, - OFStatisticsType.valueOf((short) 0, OFType.STATS_REQUEST)); - TestCase.assertEquals(OFStatisticsType.QUEUE, - OFStatisticsType.valueOf((short) 5, OFType.STATS_REQUEST)); - TestCase.assertEquals(OFStatisticsType.VENDOR, - OFStatisticsType.valueOf((short) 0xffff, OFType.STATS_REQUEST)); - } -} diff --git a/src/test/java/org/openflow/protocol/OFTypeTest.java b/src/test/java/org/openflow/protocol/OFTypeTest.java deleted file mode 100644 index c6bf0a347454064d99f0f4ec1064d17cca23da9a..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFTypeTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - - -import junit.framework.TestCase; - -import org.junit.Test; - - -public class OFTypeTest extends TestCase { - - public void testOFTypeCreate() throws Exception { - OFType foo = OFType.HELLO; - Class<? extends OFMessage> c = foo.toClass(); - TestCase.assertEquals(c, OFHello.class); - } - - @Test - public void testMapping() throws Exception { - TestCase.assertEquals(OFType.HELLO, OFType.valueOf((byte) 0)); - TestCase.assertEquals(OFType.BARRIER_REPLY, OFType.valueOf((byte) 19)); - } -} diff --git a/src/test/java/org/openflow/protocol/OFVendorTest.java b/src/test/java/org/openflow/protocol/OFVendorTest.java deleted file mode 100644 index c0385f4415824d1c79408e93ac31de4be40f3e52..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/OFVendorTest.java +++ /dev/null @@ -1,226 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.protocol; - -import java.util.Arrays; - -import junit.framework.TestCase; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.vendor.OFByteArrayVendorData; -import org.openflow.protocol.vendor.OFBasicVendorDataType; -import org.openflow.protocol.vendor.OFBasicVendorId; -import org.openflow.protocol.vendor.OFVendorData; -import org.openflow.protocol.vendor.OFVendorId; -import org.openflow.util.OFTestCase; - -public class OFVendorTest extends OFTestCase { - - public static int ACME_VENDOR_ID = 0x00112233; - - static class AcmeVendorData implements OFVendorData { - protected int dataType; - - @Override - public int getLength() { - return 4; - } - - @Override - public void readFrom(ChannelBuffer data, int length) { - dataType = data.readInt(); - } - - @Override - public void writeTo(ChannelBuffer data) { - data.writeInt(dataType); - } - } - - static class AcmeVendorData1 extends AcmeVendorData { - public short flags; - public short value; - - public static int DATA_TYPE = 1; - - public AcmeVendorData1() { - } - - public AcmeVendorData1(short flags, short value) { - this.dataType = DATA_TYPE; - this.flags = flags; - this.value = value; - } - - public short getFlags() { - return flags; - } - - public short getValue() { - return value; - } - - @Override - public int getLength() { - return 8; - } - - @Override - public void readFrom(ChannelBuffer data, int length) { - super.readFrom(data, length); - flags = data.readShort(); - value = data.readShort(); - - } - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(flags); - data.writeShort(value); - } - - public static Instantiable<OFVendorData> getInstantiable() { - return new Instantiable<OFVendorData>() { - @Override - public OFVendorData instantiate() { - return new AcmeVendorData1(); - } - }; - } - } - - static class AcmeVendorData2 extends AcmeVendorData { - public int type; - public int subtype; - - public static int DATA_TYPE = 2; - - public AcmeVendorData2() { - } - - public AcmeVendorData2(int type, int subtype) { - this.dataType = DATA_TYPE; - this.type = type; - this.subtype = subtype; - } - - public int getType() { - return type; - } - - public int getSubtype() { - return subtype; - } - - @Override - public int getLength() { - return 12; - } - - @Override - public void readFrom(ChannelBuffer data, int length) { - super.readFrom(data, length); - type = data.readShort(); - subtype = data.readShort(); - - } - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeShort(type); - data.writeShort(subtype); - } - - public static Instantiable<OFVendorData> getInstantiable() { - return new Instantiable<OFVendorData>() { - @Override - public OFVendorData instantiate() { - return new AcmeVendorData2(); - } - }; - } - } - - { - OFBasicVendorId acmeVendorId = new OFBasicVendorId(ACME_VENDOR_ID, 4); - OFVendorId.registerVendorId(acmeVendorId); - OFBasicVendorDataType acmeVendorData1 = new OFBasicVendorDataType( - AcmeVendorData1.DATA_TYPE, AcmeVendorData1.getInstantiable()); - acmeVendorId.registerVendorDataType(acmeVendorData1); - OFBasicVendorDataType acmeVendorData2 = new OFBasicVendorDataType( - AcmeVendorData2.DATA_TYPE, AcmeVendorData2.getInstantiable()); - acmeVendorId.registerVendorDataType(acmeVendorData2); - } - - private OFVendor makeVendorMessage(int vendor) { - OFVendor msg = (OFVendor) messageFactory.getMessage(OFType.VENDOR); - msg.setVendorDataFactory(BasicFactory.getInstance()); - msg.setVendor(vendor); - return msg; - } - - public void testWriteRead() throws Exception { - OFVendor msg = makeVendorMessage(1); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - TestCase.assertEquals(1, msg.getVendor()); - } - - public void testVendorData() throws Exception { - OFVendor msg = makeVendorMessage(ACME_VENDOR_ID); - OFVendorData vendorData = new AcmeVendorData1((short)11, (short)22); - msg.setVendorData(vendorData); - msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength()); - ChannelBuffer bb = ChannelBuffers.dynamicBuffer(); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - assertEquals(ACME_VENDOR_ID, msg.getVendor()); - AcmeVendorData1 vendorData1 = (AcmeVendorData1) msg.getVendorData(); - assertEquals(11, vendorData1.getFlags()); - assertEquals(22, vendorData1.getValue()); - - vendorData = new AcmeVendorData2(33, 44); - msg.setVendorData(vendorData); - msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength()); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - assertEquals(ACME_VENDOR_ID, msg.getVendor()); - AcmeVendorData2 vendorData2 = (AcmeVendorData2) msg.getVendorData(); - assertEquals(33, vendorData2.getType()); - assertEquals(44, vendorData2.getSubtype()); - - final int DUMMY_VENDOR_ID = 55; - msg.setVendor(DUMMY_VENDOR_ID); - byte[] genericVendorDataBytes = new byte[] {0x55, 0x66}; - vendorData = new OFByteArrayVendorData(genericVendorDataBytes); - msg.setVendorData(vendorData); - msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength()); - bb.clear(); - msg.writeTo(bb); - msg.readFrom(bb); - assertEquals(DUMMY_VENDOR_ID, msg.getVendor()); - OFByteArrayVendorData genericVendorData = (OFByteArrayVendorData) msg.getVendorData(); - assertTrue(Arrays.equals(genericVendorDataBytes, genericVendorData.getBytes())); - } -} diff --git a/src/test/java/org/openflow/protocol/WildcardsTest.java b/src/test/java/org/openflow/protocol/WildcardsTest.java deleted file mode 100644 index 5bf8d12314a070bc301a8ffda6a36ad02ff7d6a0..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/WildcardsTest.java +++ /dev/null @@ -1,162 +0,0 @@ -package org.openflow.protocol; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.EnumSet; - -import org.junit.Test; -import org.openflow.protocol.Wildcards.Flag; - -public class WildcardsTest { - - @Test - public void testBasic() { - int[] intMasks = { 0, 0x3820e0, OFMatch.OFPFW_ALL_SANITIZED }; - for (int i : intMasks) { - Wildcards w = Wildcards.of(i); - assertEquals(i, w.getInt()); - } - } - - @Test - public void testAllSanitize() { - Wildcards w = Wildcards.of(OFMatch.OFPFW_ALL); - assertEquals(OFMatch.OFPFW_ALL_SANITIZED, w.getInt()); - assertTrue(w.isFull()); - assertFalse(w.isExact()); - } - - @Test - public void testAll() { - Wildcards all = Wildcards.FULL; - assertTrue(all.isFull()); - assertFalse(all.isExact()); - assertEquals(0, all.getNwDstMask()); - assertEquals(0, all.getNwSrcMask()); - - // unsetting flags from NONE is a no-op - Wildcards stillAll = all.wildcard(Flag.IN_PORT); - assertTrue(stillAll.isFull()); - assertEquals(all, stillAll); - - // so is setting a >= 32 netmask - - stillAll = all.withNwSrcMask(0); - assertTrue(stillAll.isFull()); - assertEquals(all, stillAll); - - stillAll = all.withNwDstMask(0); - assertTrue(stillAll.isFull()); - assertEquals(all, stillAll); - } - - @Test - public void testNone() { - Wildcards none = Wildcards.EXACT; - assertTrue(none.isExact()); - assertEquals(32, none.getNwDstMask()); - assertEquals(32, none.getNwSrcMask()); - - // unsetting flags from NONE is a no-op - Wildcards stillNone = none.matchOn(Flag.IN_PORT); - assertTrue(stillNone.isExact()); - assertEquals(none, stillNone); - - // so is setting a >= 32 netmask - stillNone = none.withNwSrcMask(32); - assertTrue(stillNone.isExact()); - assertEquals(none, stillNone); - - stillNone = none.withNwDstMask(32); - assertTrue(stillNone.isExact()); - assertEquals(none, stillNone); - } - - @Test - public void testSetOneFlag() { - Wildcards none = Wildcards.EXACT; - assertTrue(none.isExact()); - assertFalse(none.isWildcarded(Flag.DL_SRC)); - Wildcards one = none.wildcard(Flag.DL_SRC); - assertFalse(one.isExact()); - assertTrue(one.isWildcarded(Flag.DL_SRC)); - assertEquals(OFMatch.OFPFW_DL_SRC, one.getInt()); - assertEquals(EnumSet.of(Flag.DL_SRC), one.getWildcardedFlags()); - } - - @Test - public void testSetTwoFlags() { - Wildcards none = Wildcards.EXACT; - - // set two flags - Wildcards two = none.wildcard(Flag.DL_SRC, Flag.DL_DST); - assertFalse(two.isExact()); - assertTrue(two.isWildcarded(Flag.DL_SRC)); - assertTrue(two.isWildcarded(Flag.DL_DST)); - assertEquals(OFMatch.OFPFW_DL_SRC | OFMatch.OFPFW_DL_DST, two.getInt()); - assertEquals(EnumSet.of(Flag.DL_SRC, Flag.DL_DST), two.getWildcardedFlags()); - - // unset dl_dst - Wildcards gone = two.matchOn(Flag.DL_DST); - assertFalse(gone.isExact()); - assertTrue(gone.isWildcarded(Flag.DL_SRC)); - assertFalse(gone.isWildcarded(Flag.DL_DST)); - assertEquals(OFMatch.OFPFW_DL_SRC, gone.getInt()); - assertEquals(EnumSet.of(Flag.DL_SRC), gone.getWildcardedFlags()); - } - - @Test - public void testSetNwSrc() { - Wildcards none = Wildcards.EXACT; - assertEquals(32, none.getNwSrcMask()); - - // unsetting flags from NONE is a no-op - Wildcards nwSet = none.withNwSrcMask(8); - assertFalse(nwSet.isExact()); - assertEquals(EnumSet.noneOf(Flag.class), nwSet.getWildcardedFlags()); - assertEquals(8, nwSet.getNwSrcMask()); - assertEquals((32 - 8) << OFMatch.OFPFW_NW_SRC_SHIFT, nwSet.getInt()); - } - - @Test - public void testSetNwDst() { - Wildcards none = Wildcards.EXACT; - assertEquals(32, none.getNwDstMask()); - - // unsetting flags from NONE is a no-op - Wildcards nwSet = none.withNwDstMask(8); - assertFalse(nwSet.isExact()); - assertEquals(EnumSet.noneOf(Flag.class), nwSet.getWildcardedFlags()); - assertEquals(8, nwSet.getNwDstMask()); - assertEquals((32 - 8) << OFMatch.OFPFW_NW_DST_SHIFT, nwSet.getInt()); - } - - @Test - public void testToString() { - String s = Wildcards.FULL.toString(); - assertNotNull(s); - assertTrue(s.length() > 0); - } - - @Test - public void testInvert() { - assertEquals(Wildcards.FULL, Wildcards.EXACT.inverted()); - - Wildcards some = Wildcards.of(Flag.DL_VLAN, Flag.DL_VLAN_PCP); - Wildcards inv = some.inverted(); - - for(Flag f : Flag.values()) { - boolean shouldBeSet = (f == Flag.DL_VLAN || f == Flag.DL_VLAN_PCP); - - assertEquals("Flag " + f + " " - + (shouldBeSet ? "should be set " : "should not be set"), - shouldBeSet, some.isWildcarded(f)); - assertEquals(!(f == Flag.DL_VLAN || f == Flag.DL_VLAN_PCP), inv.isWildcarded(f)); - } - assertEquals(0, inv.getNwDstMask()); - assertEquals(0, inv.getNwSrcMask()); - } -} diff --git a/src/test/java/org/openflow/protocol/action/MockVendorAction.java b/src/test/java/org/openflow/protocol/action/MockVendorAction.java deleted file mode 100644 index 49b69fb8181d4a6dd6959a40786d643fe05ead20..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/action/MockVendorAction.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.openflow.protocol.action; - -import org.jboss.netty.buffer.ChannelBuffer; - - -public class MockVendorAction extends OFActionVendor { - public static final int VENDOR_ID = 0xdeadbeef; - - private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - private byte[] mockData; - - public byte[] getMockData() { - return mockData; - } - - public void setMockData(byte[] mockData) { - this.mockData = mockData; - } - - @Override - public void readFrom(ChannelBuffer data) { - super.readFrom(data); - - int dataLength = getLength() - MINIMUM_LENGTH; - if(dataLength > 0) { - mockData = new byte[dataLength]; - data.readBytes(mockData); - } else { - mockData = EMPTY_BYTE_ARRAY; - } - - } - - @Override - public void writeTo(ChannelBuffer data) { - super.writeTo(data); - data.writeBytes(mockData); - } - - -} diff --git a/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java b/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java deleted file mode 100644 index bbc254ca0074cc9e418c5541f976d000074cf0b1..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.openflow.protocol.action; - -import org.jboss.netty.buffer.ChannelBuffer; -import org.openflow.protocol.factory.OFVendorActionFactory; - -public class MockVendorActionFactory implements OFVendorActionFactory { - - @Override - public OFActionVendor readFrom(ChannelBuffer data) { - MockVendorAction action = new MockVendorAction(); - action.readFrom(data); - return action; - } - -} diff --git a/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java b/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java deleted file mode 100644 index 31ad675d6a0a708c5a69a7ae3b0dcb21bc24e5c5..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.openflow.protocol.action; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; -import org.openflow.protocol.factory.OFVendorActionRegistry; - -public class OFVendorActionRegistryTest { - - @Test - public void test() { - MockVendorActionFactory factory = new MockVendorActionFactory(); - OFVendorActionRegistry.getInstance().register(MockVendorAction.VENDOR_ID, factory); - assertEquals(factory, OFVendorActionRegistry.getInstance().get(MockVendorAction.VENDOR_ID)); - } - -} diff --git a/src/test/java/org/openflow/util/HexStringTest.java b/src/test/java/org/openflow/util/HexStringTest.java deleted file mode 100644 index a8f8ba4b89760e797255da01e3cecb162f0da41b..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/HexStringTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import org.junit.Test; - -import junit.framework.TestCase; - -/** - * Does hexstring conversion work? - * - * @author Rob Sherwood (rob.sherwood@stanford.edu) - * - */ - -public class HexStringTest extends TestCase { - - @Test - public void testMarshalling() throws Exception { - String dpidStr = "00:00:00:23:20:2d:16:71"; - long dpid = HexString.toLong(dpidStr); - String testStr = HexString.toHexString(dpid); - TestCase.assertEquals(dpidStr, testStr); - } - - @Test - public void testToLong() { - String dpidStr = "3e:1f:01:fc:72:8c:63:31"; - long valid = 0x3e1f01fc728c6331L; - long testLong = HexString.toLong(dpidStr); - TestCase.assertEquals(valid, testLong); - } - - @Test - public void testToLongMSB() { - String dpidStr = "ca:7c:5e:d1:64:7a:95:9b"; - long valid = -3856102927509056101L; - long testLong = HexString.toLong(dpidStr); - TestCase.assertEquals(valid, testLong); - } - - @Test - public void testToLongError() { - String dpidStr = "09:08:07:06:05:04:03:02:01"; - try { - HexString.toLong(dpidStr); - fail("HexString.toLong() should have thrown a NumberFormatException"); - } - catch (NumberFormatException expected) { - // do nothing - } - } - - @Test - public void testToStringBytes() { - byte[] dpid = { 0, 0, 0, 0, 0, 0, 0, -1 }; - String valid = "00:00:00:00:00:00:00:ff"; - String testString = HexString.toHexString(dpid); - TestCase.assertEquals(valid, testString); - } - - @Test - public void testFromHexStringError() { - String invalidStr = "00:00:00:00:00:00:ffff"; - try { - HexString.fromHexString(invalidStr); - fail("HexString.fromHexString() should have thrown a NumberFormatException"); - } - catch (NumberFormatException expected) { - // do nothing - } - } -} diff --git a/src/test/java/org/openflow/util/OFTestCase.java b/src/test/java/org/openflow/util/OFTestCase.java deleted file mode 100644 index 07bee2d589a1901ad1f77afc3a2ee262a48be429..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/OFTestCase.java +++ /dev/null @@ -1,36 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.OFMessageFactory; - -import junit.framework.TestCase; - -public class OFTestCase extends TestCase { - public OFMessageFactory messageFactory; - - @Override - protected void setUp() throws Exception { - super.setUp(); - messageFactory = BasicFactory.getInstance(); - } - - public void test() throws Exception { - } -} diff --git a/src/test/java/org/openflow/util/U16Test.java b/src/test/java/org/openflow/util/U16Test.java deleted file mode 100644 index ba87e7b122d5cdb101a6d5a74898a612cb57fcdd..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/U16Test.java +++ /dev/null @@ -1,33 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import junit.framework.TestCase; - -public class U16Test extends TestCase { - /** - * Tests that we correctly translate unsigned values in and out of a short - * @throws Exception - */ - public void test() throws Exception { - int val = 0xffff; - TestCase.assertEquals((short)-1, U16.t(val)); - TestCase.assertEquals((short)32767, U16.t(0x7fff)); - TestCase.assertEquals(val, U16.f((short)-1)); - } -} diff --git a/src/test/java/org/openflow/util/U32Test.java b/src/test/java/org/openflow/util/U32Test.java deleted file mode 100644 index 223c1034e74cef66403f3c786a30f771a88b970b..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/U32Test.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import junit.framework.TestCase; - -public class U32Test extends TestCase { - /** - * Tests that we correctly translate unsigned values in and out of an int - * @throws Exception - */ - public void test() throws Exception { - long val = 0xffffffffL; - TestCase.assertEquals(-1, U32.t(val)); - TestCase.assertEquals(val, U32.f(-1)); - } -} diff --git a/src/test/java/org/openflow/util/U64Test.java b/src/test/java/org/openflow/util/U64Test.java deleted file mode 100644 index 0a97e302f78e84700a0407b5770766eea339ffd4..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/U64Test.java +++ /dev/null @@ -1,34 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.math.BigInteger; - -import junit.framework.TestCase; - -public class U64Test extends TestCase { - /** - * Tests that we correctly translate unsigned values in and out of a long - * @throws Exception - */ - public void test() throws Exception { - BigInteger val = new BigInteger("ffffffffffffffff", 16); - TestCase.assertEquals(-1, U64.t(val)); - TestCase.assertEquals(val, U64.f(-1)); - } -} diff --git a/src/test/java/org/openflow/util/U8Test.java b/src/test/java/org/openflow/util/U8Test.java deleted file mode 100644 index 2c06c4db31f56699dbcac37d1f4296d1ad16342d..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/U8Test.java +++ /dev/null @@ -1,32 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import junit.framework.TestCase; - -public class U8Test extends TestCase { - /** - * Tests that we correctly translate unsigned values in and out of a byte - * @throws Exception - */ - public void test() throws Exception { - short val = 0xff; - TestCase.assertEquals(-1, U8.t(val)); - TestCase.assertEquals(val, U8.f((byte)-1)); - } -} diff --git a/src/test/java/org/openflow/util/UnsignedTest.java b/src/test/java/org/openflow/util/UnsignedTest.java deleted file mode 100644 index 7cdf7391bccd390ca941338cf99563dbb9da229c..0000000000000000000000000000000000000000 --- a/src/test/java/org/openflow/util/UnsignedTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/** -* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior -* University -* -* 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 org.openflow.util; - -import java.math.BigInteger; -import java.nio.ByteBuffer; - -import junit.framework.TestCase; - -public class UnsignedTest extends TestCase { - public static String ULONG_MAX = "18446744073709551615"; - - /** - * Tests that we correctly extract an unsigned long into a BigInteger - * @throws Exception - */ - public void testGetUnsignedLong() throws Exception { - ByteBuffer bb = ByteBuffer.allocate(8); - bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff); - bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff); - bb.position(0); - bb.limit(8); - BigInteger bi = Unsigned.getUnsignedLong(bb); - BigInteger uLongMax = new BigInteger(ULONG_MAX); - for (int i = 0; i < uLongMax.bitCount(); ++i) { - TestCase.assertTrue("Bit: " + i + " should be: " + uLongMax.testBit(i), - uLongMax.testBit(i) == bi.testBit(i)); - } - TestCase.assertEquals(ULONG_MAX, bi.toString()); - - bb = ByteBuffer.allocate(10); - bb.put((byte)0x00); - bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff); - bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff); - bb.put((byte)0x00); - bb.position(0); - bb.limit(10); - bi = Unsigned.getUnsignedLong(bb, 1); - uLongMax = new BigInteger(ULONG_MAX); - for (int i = 0; i < uLongMax.bitCount(); ++i) { - TestCase.assertTrue("Bit: " + i + " should be: " + uLongMax.testBit(i), - uLongMax.testBit(i) == bi.testBit(i)); - } - TestCase.assertEquals(ULONG_MAX, bi.toString()); - } - - /** - * Tests that we correctly put an unsigned long into a ByteBuffer - * @throws Exception - */ - public void testPutUnsignedLong() throws Exception { - ByteBuffer bb = ByteBuffer.allocate(8); - BigInteger uLongMax = new BigInteger(ULONG_MAX); - Unsigned.putUnsignedLong(bb, uLongMax); - for (int i = 0; i < 8; ++i) { - TestCase.assertTrue("Byte: " + i + " should be 0xff, was: " + bb.get(i), - (bb.get(i) & (short)0xff) == 0xff); - } - - bb = ByteBuffer.allocate(10); - Unsigned.putUnsignedLong(bb, uLongMax, 1); - int offset = 1; - for (int i = 0; i < 8; ++i) { - TestCase.assertTrue("Byte: " + i + " should be 0xff, was: " + - bb.get(offset+i), (bb.get(offset+i) & (short)0xff) == 0xff); - } - } -}