import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.core.IContainer;
import org.opendaylight.controller.sal.core.IContainerListener;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.switchmanager.IInventoryListener;
IForwardingRulesManager.class.getName(),
IInventoryListener.class.getName(),
ICacheUpdateAware.class.getName(),
- IConfigurationContainerAware.class.getName() };
+ IConfigurationContainerAware.class.getName(),
+ IFlowProgrammerListener.class.getName()};
} else {
interfaces = new String[] {
ISwitchManagerAware.class.getName(),
IForwardingRulesManager.class.getName(),
IInventoryListener.class.getName(),
ICacheUpdateAware.class.getName(),
- IConfigurationContainerAware.class.getName() };
+ IConfigurationContainerAware.class.getName(),
+ IFlowProgrammerListener.class.getName()};
}
c.setInterface(interfaces, props);
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.opendaylight.controller.sal.core.Property;
import org.opendaylight.controller.sal.core.UpdateType;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
public class ForwardingRulesManagerImpl implements IForwardingRulesManager,
PortGroupChangeListener, IContainerListener, ISwitchManagerAware,
IConfigurationContainerAware, IInventoryListener, IObjectReader,
- ICacheUpdateAware<Long, String>, CommandProvider {
+ ICacheUpdateAware<Long, String>, CommandProvider,
+ IFlowProgrammerListener {
private static final String SAVE = "Save";
private static final String NODEDOWN = "Node is Down";
private static final Logger log = LoggerFactory
private boolean inContainerMode; // being used by default instance only
/*
* Flow database. It's the software view of what was installed on the
- * switch. It is indexed by node. For convenience a version indexed
- * by group name is also maintained. The core element is a class which
- * contains the flow entry pushed by the functional modules and the
- * respective container flow merged version. In absence of container
- * flows, the two flow entries are the same.
+ * switch. It is indexed by node. For convenience a version indexed by group
+ * name is also maintained. The core element is a class which contains the
+ * flow entry pushed by the functional modules and the respective container
+ * flow merged version. In absence of container flows, the two flow entries
+ * are the same.
*/
private ConcurrentMap<Node, Set<FlowEntryInstall>> nodeFlows;
private ConcurrentMap<String, Set<FlowEntryInstall>> groupFlows;
/*
- * Inactive flow list. This is for the global instance of FRM
- * It will contain all the flow entries which were installed on the
- * global container when the first container is created.
+ * Inactive flow list. This is for the global instance of FRM It will
+ * contain all the flow entries which were installed on the global container
+ * when the first container is created.
*/
private List<FlowEntry> inactiveFlows;
private ISwitchManager switchManager;
/**
- * Adds a flow entry onto the network node
- * It runs various validity checks and derive the final container flows
- * merged entries that will be attempted to be installed
- *
- * @param flowEntry the original flow entry application requested to add
+ * Adds a flow entry onto the network node It runs various validity checks
+ * and derive the final container flows merged entries that will be
+ * attempted to be installed
+ *
+ * @param flowEntry
+ * the original flow entry application requested to add
* @return
*/
private Status addEntry(FlowEntry flowEntry) {
// Sanity Check
if (flowEntry == null || flowEntry.getNode() == null) {
- String msg = "Invalid FlowEntry";
+ String msg = "Invalid FlowEntry";
log.warn(msg + ": " + flowEntry);
return new Status(StatusCode.NOTACCEPTABLE, msg);
}
/*
- * Derive the container flow merged entries to install
- * In presence of N container flows, we may end up with
- * N different entries to install...
+ * Derive the container flow merged entries to install In presence of N
+ * container flows, we may end up with N different entries to install...
*/
- List<FlowEntryInstall> toInstallList = deriveInstallEntries(flowEntry
- .clone(), container.getContainerFlows());
+ List<FlowEntryInstall> toInstallList = deriveInstallEntries(
+ flowEntry.clone(), container.getContainerFlows());
// Container Flow conflict Check
if (toInstallList.isEmpty()) {
- String msg = "Flow Entry conflicts with all Container Flows";
- log.warn(msg);
+ String msg = "Flow Entry conflicts with all Container Flows";
+ log.warn(msg);
return new Status(StatusCode.CONFLICT, msg);
}
// Derive the list of entries good to be installed
List<FlowEntryInstall> toInstallSafe = new ArrayList<FlowEntryInstall>();
for (FlowEntryInstall entry : toInstallList) {
- // Conflict Check: Verify new entry would not overwrite existing ones
+ // Conflict Check: Verify new entry would not overwrite existing
+ // ones
if (findMatch(entry.getInstall(), false) != null) {
- log.warn("Operation Rejected: A flow with same match " +
- "and priority exists on the target node");
+ log.warn("Operation Rejected: A flow with same match "
+ + "and priority exists on the target node");
log.trace("Aborting to install " + entry);
continue;
}
toInstallSafe.add(entry);
}
- // Declare failure if all the container flow merged entries clash with existing entries
+ // Declare failure if all the container flow merged entries clash with
+ // existing entries
if (toInstallSafe.size() == 0) {
- String msg = "A flow with same match and priority exists " +
- "on the target node";
- log.warn(msg);
+ String msg = "A flow with same match and priority exists "
+ + "on the target node";
+ log.warn(msg);
return new Status(StatusCode.CONFLICT, msg);
}
for (FlowEntryInstall installEntry : toInstallList) {
// Install and update database
- Status ret = addEntriesInternal(installEntry);
+ Status ret = addEntriesInternal(installEntry);
if (ret.isSuccess()) {
oneSucceded = true;
* of container flow merged flow entries good to be installed on this
* container. If the list of container flows is null or empty, the install
* entry list will contain only one entry, the original flow entry. If the
- * flow entry is congruent with all the N container flows, then the output
+ * flow entry is congruent with all the N container flows, then the output
* install entry list will contain N entries. If the output list is empty,
* it means the passed flow entry conflicts with all the container flows.
- *
- * @param cFlowList The list of container flows
- * @return the list of container flow merged entries good to be installed on this container
+ *
+ * @param cFlowList
+ * The list of container flows
+ * @return the list of container flow merged entries good to be installed on
+ * this container
*/
private List<FlowEntryInstall> deriveInstallEntries(FlowEntry request,
List<ContainerFlow> cFlowList) {
toInstallList.add(new FlowEntryInstall(request.clone(), null));
} else {
// Create the list of entries to be installed. If the flow entry is
- // not congruent with any container flow, no install entries will be created
+ // not congruent with any container flow, no install entries will be
+ // created
for (ContainerFlow cFlow : container.getContainerFlows()) {
if (cFlow.allowsFlow(request.getFlow())) {
toInstallList.add(new FlowEntryInstall(request.clone(),
}
/**
- * Modify a flow entry with a new one
- * It runs various validity check and derive the final container flows
- * merged flow entries to work with
- *
+ * Modify a flow entry with a new one It runs various validity check and
+ * derive the final container flows merged flow entries to work with
+ *
* @param currentFlowEntry
* @param newFlowEntry
* @return Success or error string
*/
private Status modifyEntry(FlowEntry currentFlowEntry,
FlowEntry newFlowEntry) {
- Status retExt;
+ Status retExt;
// Sanity checks
if (currentFlowEntry == null || currentFlowEntry.getNode() == null
|| newFlowEntry == null || newFlowEntry.getNode() == null) {
- String msg ="Modify: Invalid FlowEntry";
+ String msg = "Modify: Invalid FlowEntry";
log.warn(msg + ": {} or {} ", currentFlowEntry, newFlowEntry);
return new Status(StatusCode.NOTACCEPTABLE, msg);
}
if (!currentFlowEntry.getNode().equals(newFlowEntry.getNode())
|| !currentFlowEntry.getFlowName().equals(
newFlowEntry.getFlowName())) {
- String msg = "Modify: Incompatible Flow Entries";
- log.warn(msg +": {} and {}", currentFlowEntry, newFlowEntry);
+ String msg = "Modify: Incompatible Flow Entries";
+ log.warn(msg + ": {} and {}", currentFlowEntry, newFlowEntry);
return new Status(StatusCode.NOTACCEPTABLE, msg);
}
// Equality Check
if (currentFlowEntry.equals(newFlowEntry)) {
- String msg = "Modify skipped as flows are the same";
+ String msg = "Modify skipped as flows are the same";
log.debug(msg + ": " + currentFlowEntry + " and " + newFlowEntry);
return new Status(StatusCode.SUCCESS, msg);
}
- // Conflict Check: Verify the new entry would not conflict with another existing one
- // This is a loose check on the previous original flow entry requests. No check
+ // Conflict Check: Verify the new entry would not conflict with another
+ // existing one
+ // This is a loose check on the previous original flow entry requests.
+ // No check
// on the container flow merged flow entries (if any) yet
FlowEntryInstall sameMatchOriginalEntry = findMatch(newFlowEntry, true);
if (sameMatchOriginalEntry != null
&& !sameMatchOriginalEntry.getOriginal().equals(
currentFlowEntry)) {
- String msg = "Operation Rejected: Another flow with same match " +
- "and priority exists on the target node";
+ String msg = "Operation Rejected: Another flow with same match "
+ + "and priority exists on the target node";
log.warn(msg);
return new Status(StatusCode.CONFLICT, msg);
}
newFlowEntry.clone(), container.getContainerFlows());
if (toInstallList.isEmpty()) {
- String msg = "Modify Operation Rejected: The new entry " +
- "conflicts with all the container flows";
+ String msg = "Modify Operation Rejected: The new entry "
+ + "conflicts with all the container flows";
log.warn(msg);
return new Status(StatusCode.CONFLICT, msg);
}
* This is only possible when the new entry and current entry have
* different match. In this scenario the modification would ultimately
* be handled as a remove and add operations in the protocol plugin.
- *
+ *
* Also, if any of the new flow entries would clash with an existing
* one, we cannot proceed with the modify operation, because it would
* fail for some entries and leave stale entries on the network node.
- * Modify path can be taken only if it can be performed completely,
- * for all entries.
- *
- * So, for the above two cases, to simplify, let's decouple the modify in:
- * 1) remove current entries
- * 2) install new entries
+ * Modify path can be taken only if it can be performed completely, for
+ * all entries.
+ *
+ * So, for the above two cases, to simplify, let's decouple the modify
+ * in: 1) remove current entries 2) install new entries
*/
boolean decouple = false;
if (installedList.size() != toInstallList.size()) {
- log.info("Modify: New flow entry does not satisfy the same " +
- "number of container flows as the original entry does");
+ log.info("Modify: New flow entry does not satisfy the same "
+ + "number of container flows as the original entry does");
decouple = true;
}
List<FlowEntryInstall> toInstallSafe = new ArrayList<FlowEntryInstall>();
for (FlowEntryInstall installEntry : toInstallList) {
- // Conflict Check: Verify the new entry would not overwrite another existing one
- FlowEntryInstall sameMatchEntry = findMatch(installEntry
- .getInstall(), false);
+ // Conflict Check: Verify the new entry would not overwrite another
+ // existing one
+ FlowEntryInstall sameMatchEntry = findMatch(
+ installEntry.getInstall(), false);
if (sameMatchEntry != null
&& !sameMatchEntry.getOriginal().equals(currentFlowEntry)) {
- log.info("Modify: new container flow merged flow entry " +
- "clashes with existing flow");
+ log.info("Modify: new container flow merged flow entry "
+ + "clashes with existing flow");
decouple = true;
} else {
toInstallSafe.add(installEntry);
/*
* The two list have the same size and the entries to install do not
* clash with any existing flow on the network node. We assume here
- * (and might be wrong) that the same container flows that were satisfied
- * by the current entries are the same that are satisfied by the new
- * entries. Let's take the risk for now.
- *
+ * (and might be wrong) that the same container flows that were
+ * satisfied by the current entries are the same that are satisfied
+ * by the new entries. Let's take the risk for now.
+ *
* Note: modification has to be complete. If any entry modification
- * fails, we need to stop, restore the already modified entries,
- * and declare failure.
+ * fails, we need to stop, restore the already modified entries, and
+ * declare failure.
*/
Status retModify;
int i = 0;
}
// Check if uncompleted modify
if (i < size) {
- log.warn("Unable to perform a complete modify for all " +
- "the container flows merged entries");
+ log.warn("Unable to perform a complete modify for all "
+ + "the container flows merged entries");
// Restore original entries
int j = 0;
while (j < i) {
}
// Fatal error, recovery failed
if (j < i) {
- String msg = "Flow recovery failed ! Unrecoverable Error";
+ String msg = "Flow recovery failed ! Unrecoverable Error";
log.error(msg);
return new Status(StatusCode.INTERNALERROR, msg);
}
/**
* This is the function that modifies the final container flows merged
- * entries on the network node and update the database. It expects that
- * all the validity checks are passed
- *
+ * entries on the network node and update the database. It expects that all
+ * the validity checks are passed
+ *
* @param currentEntries
* @param newEntries
* @return
.getFlow());
if (!status.isSuccess()) {
- log.warn("SDN Plugin failed to program the flow: " + status.getDescription());
+ log.warn("SDN Plugin failed to program the flow: "
+ + status.getDescription());
return status;
}
- log.trace("Modified {} => {}", currentEntries.getInstall(), newEntries
- .getInstall());
+ log.trace("Modified {} => {}", currentEntries.getInstall(),
+ newEntries.getInstall());
// Update DB
updateLocalDatabase(currentEntries, false);
/**
* Remove a flow entry. If the entry is not present in the software view
* (entry or node not present), it return successfully
- *
+ *
* @param flowEntry
* @return
*/
private Status removeEntry(FlowEntry flowEntry) {
Status error = new Status(null, null);
-
+
// Sanity Check
if (flowEntry == null || flowEntry.getNode() == null) {
- String msg = "Invalid FlowEntry";
+ String msg = "Invalid FlowEntry";
log.warn(msg + ": " + flowEntry);
return new Status(StatusCode.NOTACCEPTABLE, msg);
}
// Derive the container flows merged installed entries
- List<FlowEntryInstall> installedList = deriveInstallEntries(flowEntry
- .clone(), container.getContainerFlows());
+ List<FlowEntryInstall> installedList = deriveInstallEntries(
+ flowEntry.clone(), container.getContainerFlows());
Set<FlowEntryInstall> flowsOnNode = nodeFlows.get(flowEntry.getNode());
boolean atLeastOneRemoved = false;
for (FlowEntryInstall entry : installedList) {
if (flowsOnNode == null) {
- String msg = "Removal skipped (Node down)";
+ String msg = "Removal skipped (Node down or Flow not on Node)";
log.debug(msg + " for flow entry " + flowEntry);
return new Status(StatusCode.SUCCESS, msg);
}
}
/*
- * No worries if full removal failed. Consistency checker will
- * take care of removing the stale entries later, or adjusting
- * the software database if not in sync with hardware
+ * No worries if full removal failed. Consistency checker will take care
+ * of removing the stale entries later, or adjusting the software
+ * database if not in sync with hardware
*/
- return (atLeastOneRemoved) ?
- new Status(StatusCode.SUCCESS, null) : error;
+ return (atLeastOneRemoved) ? new Status(StatusCode.SUCCESS, null)
+ : error;
}
/**
* This is the function that removes the final container flows merged entry
* from the network node and update the database. It expects that all the
* validity checks are passed
- *
- * @param entry the FlowEntryInstall
+ *
+ * @param entry
+ * the FlowEntryInstall
* @return "Success" or error string
*/
private Status removeEntryInternal(FlowEntryInstall entry) {
entry.toBeDeleted();
// Remove from node
- Status status =
- programmer.removeFlow(entry.getNode(),
- entry.getInstall().getFlow());
+ Status status = programmer.removeFlow(entry.getNode(), entry
+ .getInstall().getFlow());
if (!status.isSuccess()) {
- log.warn("SDN Plugin failed to remove the flow: " +
- status.getDescription());
+ log.warn("SDN Plugin failed to remove the flow: "
+ + status.getDescription());
return status;
}
log.trace("Removed {}", entry.getInstall());
* on the network node and updates the database. It expects that all the
* validity and conflict checks are passed. That means it does not check
* whether this flow would conflict or overwrite an existing one.
- *
- * @param entry the FlowEntryInstall
+ *
+ * @param entry
+ * the FlowEntryInstall
* @return "Success" or error string
*/
private Status addEntriesInternal(FlowEntryInstall entry) {
// Install the flow on the network node
- Status status = programmer.addFlow(entry.getNode(),
- entry.getInstall().getFlow());
+ Status status = programmer.addFlow(entry.getNode(), entry.getInstall()
+ .getFlow());
if (!status.isSuccess()) {
- log.warn("SDN Plugin failed to program the flow: " +
- status.getDescription());
+ log.warn("SDN Plugin failed to program the flow: "
+ + status.getDescription());
return status;
}
}
/**
- * Returns true if the flow conflicts with all the container's flows.
- * This means that if the function returns true, the passed flow entry
- * is congruent with at least one container flow, hence it is good to
- * be installed on this container.
- *
+ * Returns true if the flow conflicts with all the container's flows. This
+ * means that if the function returns true, the passed flow entry is
+ * congruent with at least one container flow, hence it is good to be
+ * installed on this container.
+ *
* @param flowEntry
- * @return true if flow conflicts with all the container flows, false otherwise
+ * @return true if flow conflicts with all the container flows, false
+ * otherwise
*/
private boolean entryConflictsWithContainerFlows(FlowEntry flowEntry) {
List<ContainerFlow> cFlowList = container.getContainerFlows();
// Validity check and avoid unnecessary computation
- // Also takes care of default container where no container flows are present
+ // Also takes care of default container where no container flows are
+ // present
if (cFlowList == null || cFlowList.isEmpty()) {
return false;
}
@Override
public Status installFlowEntry(FlowEntry flowEntry) {
- Status status;
+ Status status;
if (inContainerMode) {
- String msg = "Controller in container mode: Install Refused";
+ String msg = "Controller in container mode: Install Refused";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(msg);
} else {
@Override
public Status uninstallFlowEntry(FlowEntry entry) {
- Status status;
+ Status status;
if (inContainerMode) {
- String msg = "Controller in container mode: Uninstall Refused";
+ String msg = "Controller in container mode: Uninstall Refused";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(msg);
} else {
- status = removeEntry(entry);
+ status = removeEntry(entry);
}
return status;
}
@Override
public Status modifyFlowEntry(FlowEntry currentFlowEntry,
FlowEntry newFlowEntry) {
- Status status = null;
+ Status status = null;
if (inContainerMode) {
String msg = "Controller in container mode: Modify Refused";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
/*
* Run a loose check on the installed entries to decide whether to go
* with a add or modify method. A loose check means only check against
- * the original flow entry requests and not against the installed
- * flow entries which are the result of the original entry merged with
- * the container flow(s) (if any). The modifyFlowEntry method in
- * presence of conflicts with the Container flows (if any) would revert
- * back to a delete + add pattern
+ * the original flow entry requests and not against the installed flow
+ * entries which are the result of the original entry merged with the
+ * container flow(s) (if any). The modifyFlowEntry method in presence of
+ * conflicts with the Container flows (if any) would revert back to a
+ * delete + add pattern
*/
FlowEntryInstall currentFlowEntries = findMatch(newFlowEntry, true);
}
/**
- * Try to find in the database if a Flow with the same Match and priority
- * of the passed one already exists for the specified network node.
- * Flow, priority and network node are all specified in the FlowEntry
- * If found, the respective FlowEntryInstall Object is returned
- *
- * @param flowEntry the FlowEntry to be tested against the ones installed
- * @param looseCheck if true, the function will run the check against the
- * original flow entry portion of the installed entries
+ * Try to find in the database if a Flow with the same Match and priority of
+ * the passed one already exists for the specified network node. Flow,
+ * priority and network node are all specified in the FlowEntry If found,
+ * the respective FlowEntryInstall Object is returned
+ *
+ * @param flowEntry
+ * the FlowEntry to be tested against the ones installed
+ * @param looseCheck
+ * if true, the function will run the check against the original
+ * flow entry portion of the installed entries
* @return null if not found, otherwise the FlowEntryInstall which contains
- * the existing flow entry
+ * the existing flow entry
*/
private FlowEntryInstall findMatch(FlowEntry flowEntry, boolean looseCheck) {
Flow flow = flowEntry.getFlow();
}
/**
- * Updates all installed flows because the container flow got updated
- * This is obtained in two phases on per node basis:
- * 1) Uninstall of all flows
- * 2) Reinstall of all flows
- * This is needed because a new container flows merged flow may conflict with an existing
- * old container flows merged flow on the network node
+ * Updates all installed flows because the container flow got updated This
+ * is obtained in two phases on per node basis: 1) Uninstall of all flows 2)
+ * Reinstall of all flows This is needed because a new container flows
+ * merged flow may conflict with an existing old container flows merged flow
+ * on the network node
*/
private void updateFlowsContainerFlow() {
List<FlowEntryInstall> oldCouples = new ArrayList<FlowEntryInstall>();
if (entry.getValue() == null) {
continue;
}
- // Create a set of old entries and one of original entries to be reinstalled
+ // Create a set of old entries and one of original entries to be
+ // reinstalled
for (FlowEntryInstall oldCouple : entry.getValue()) {
oldCouples.add(oldCouple);
toReinstall.add(oldCouple.getOriginal());
}
- // Remove the old couples. No validity checks to be run, use the internal remove
+ // Remove the old couples. No validity checks to be run, use the
+ // internal remove
for (FlowEntryInstall oldCouple : oldCouples) {
this.removeEntryInternal(oldCouple);
}
- // Reinstall the original flow entries, via the regular path: new cFlow merge + validations
+ // Reinstall the original flow entries, via the regular path: new
+ // cFlow merge + validations
for (FlowEntry flowEntry : toReinstall) {
this.installFlowEntry(flowEntry);
}
flowName);
} else {
log.warn("Failed to add ports {} to Flow entry {}: "
- + error.getDescription(), portList,
+ + error.getDescription(), portList,
currentFlowEntry.toString());
}
return;
flowName);
} else {
log.warn("Failed to remove ports {} from Flow entry {}: "
- + status.getDescription(), portList,
+ + status.getDescription(), portList,
currentFlowEntry.toString());
}
return;
}
}
- log
- .warn(
- "Failed to remove ports from Flow {} on Node {}: Entry Not Found",
- flowName, node);
+ log.warn(
+ "Failed to remove ports from Flow {} on Node {}: Entry Not Found",
+ flowName, node);
}
/*
}
}
if (currentFlowEntry == null) {
- log
- .warn(
- "Failed to replace output port for flow {} on node {}: Entry Not Found",
- flowName, node);
+ log.warn(
+ "Failed to replace output port for flow {} on node {}: Entry Not Found",
+ flowName, node);
return;
}
@SuppressWarnings("deprecation")
private void allocateCaches() {
if (this.clusterContainerService == null) {
- log
- .warn("Un-initialized clusterContainerService, can't create cache");
+ log.warn("Un-initialized clusterContainerService, can't create cache");
return;
}
log.debug("FRM allocateCaches for Container {}", container);
try {
- clusterContainerService.createCache("frm.nodeFlows", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.nodeFlows",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache("frm.groupFlows", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.groupFlows",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache("frm.staticFlows", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.staticFlows",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache("frm.flowsSaveEvent", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.flowsSaveEvent",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
clusterContainerService.createCache("frm.staticFlowsOrdinal",
EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache("frm.portGroupConfigs", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.portGroupConfigs",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache("frm.portGroupData", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.portGroupData",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
- clusterContainerService.createCache("frm.TSPolicies", EnumSet
- .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.TSPolicies",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
} catch (CacheConfigException cce) {
log.error("FRM CacheConfigException");
}
}
- @SuppressWarnings( { "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked", "deprecation" })
private void retrieveCaches() {
ConcurrentMap<?, ?> map;
if (this.clusterContainerService == null) {
- log
- .warn("un-initialized clusterContainerService, can't retrieve cache");
+ log.warn("un-initialized clusterContainerService, can't retrieve cache");
return;
}
if (map != null) {
nodeFlows = (ConcurrentMap<Node, Set<FlowEntryInstall>>) map;
} else {
- log
- .error(
- "FRM Cache frm.nodeFlows allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.nodeFlows allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.groupFlows");
if (map != null) {
groupFlows = (ConcurrentMap<String, Set<FlowEntryInstall>>) map;
} else {
- log
- .error(
- "FRM Cache frm.groupFlows allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.groupFlows allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.staticFlows");
if (map != null) {
staticFlows = (ConcurrentMap<Integer, FlowConfig>) map;
} else {
- log
- .error(
- "FRM Cache frm.staticFlows allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.staticFlows allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.flowsSaveEvent");
if (map != null) {
flowsSaveEvent = (ConcurrentMap<Long, String>) map;
} else {
- log
- .error(
- "FRM Cache frm.flowsSaveEvent allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.flowsSaveEvent allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.staticFlowsOrdinal");
if (map != null) {
staticFlowsOrdinal = (ConcurrentMap<Integer, Integer>) map;
} else {
- log
- .error(
- "FRM Cache frm.staticFlowsOrdinal allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.staticFlowsOrdinal allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.portGroupConfigs");
if (map != null) {
portGroupConfigs = (ConcurrentMap<String, PortGroupConfig>) map;
} else {
- log
- .error(
- "FRM Cache frm.portGroupConfigs allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.portGroupConfigs allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.portGroupData");
if (map != null) {
portGroupData = (ConcurrentMap<PortGroupConfig, Map<Node, PortGroup>>) map;
} else {
- log
- .error(
- "FRM Cache frm.portGroupData allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.portGroupData allocation failed for Container {}",
+ container);
}
map = clusterContainerService.getCache("frm.TSPolicies");
if (map != null) {
TSPolicies = (ConcurrentMap<String, Object>) map;
} else {
- log
- .error(
- "FRM Cache frm.TSPolicies allocation failed for Container {}",
- container);
+ log.error(
+ "FRM Cache frm.TSPolicies allocation failed for Container {}",
+ container);
}
}
@SuppressWarnings("deprecation")
- private void destroyCaches() {
+ private void destroyCaches() {
if (this.clusterContainerService == null) {
- log
- .warn("Un-initialized clusterContainerService, can't destroy cache");
+ log.warn("Un-initialized clusterContainerService, can't destroy cache");
return;
}
* multiple entry configuration (PortGroup) and hardware installation is
* NOT done directly on this event. 3. The User prefers to retain the
* configuration in Controller and skip hardware installation.
- *
+ *
* Hence it is safe to update the StaticFlow DB at this point.
- *
+ *
* Note : For the case of PortGrouping, it is essential to have this DB
* populated before the PortGroupListeners can query for the DB
* triggered using portGroupChanged event...
if (config.getNode().equals(node)) {
if (config.installInHw()
&& !config.getStatus().equals(
- StatusCode.SUCCESS.toString())) {
+ StatusCode.SUCCESS.toString())) {
Status status = this.addEntry(config.getFlowEntry());
config.setStatus(status.getDescription());
}
log.trace("Updating Static Flow configs on node down: " + node);
List<Integer> toRemove = new ArrayList<Integer>();
- for (Entry<Integer,FlowConfig> entry : staticFlows.entrySet()) {
+ for (Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
- FlowConfig config = entry.getValue();
+ FlowConfig config = entry.getValue();
if (config.isPortGroupEnabled()) {
continue;
}
-
+
if (config.installInHw() && config.getNode().equals(node)) {
- if (config.isInternalFlow()) {
- // Take note of this controller generated static flow
- toRemove.add(entry.getKey());
- } else {
- config.setStatus(NODEDOWN);
- }
+ if (config.isInternalFlow()) {
+ // Take note of this controller generated static flow
+ toRemove.add(entry.getKey());
+ } else {
+ config.setStatus(NODEDOWN);
+ }
}
}
- // Remove controller generated static flows for this node
+ // Remove controller generated static flows for this node
for (Integer index : toRemove) {
- staticFlows.remove(index);
- }
+ staticFlows.remove(index);
+ }
}
private void updateStaticFlowConfigsOnContainerModeChange(UpdateType update) {
if (config.installInHw()) {
switch (update) {
case ADDED:
- config
- .setStatus("Removed from node because in container mode");
+ config.setStatus("Removed from node because in container mode");
break;
case REMOVED:
config.setStatus(StatusCode.SUCCESS.toString());
public Status removeStaticFlow(FlowConfig config) {
/*
* No config.isInternal() check as NB does not take this path and GUI
- * cannot issue a delete on an internal generated flow. We need this path
- * to be accessible when switch mode is changed from proactive to
+ * cannot issue a delete on an internal generated flow. We need this
+ * path to be accessible when switch mode is changed from proactive to
* reactive, so that we can remove the internal generated LLDP and ARP
* punt flows
*/
for (Map.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
if (entry.getValue().isByNameAndNodeIdEqual(config)) {
// Program the network node
- Status status = this.removeEntry(config.getFlowEntry());
+ Status status = this.removeEntry(config.getFlowEntry());
// Update configuration database if programming was successful
if (status.isSuccess()) {
staticFlows.remove(entry.getKey());
public Status removeStaticFlow(String name, Node node) {
for (Map.Entry<Integer, FlowConfig> mapEntry : staticFlows.entrySet()) {
FlowConfig entry = mapEntry.getValue();
- Status status = new Status(null,null);
+ Status status = new Status(null, null);
if (entry.isByNameAndNodeIdEqual(name, node)) {
// Validity check for api3 entry point
if (entry.isInternalFlow()) {
- String msg = "Invalid operation: Controller generated " +
- "flow cannot be deleted";
- log.warn(msg);
- return new Status(StatusCode.NOTACCEPTABLE, msg);
+ String msg = "Invalid operation: Controller generated "
+ + "flow cannot be deleted";
+ log.warn(msg);
+ return new Status(StatusCode.NOTACCEPTABLE, msg);
}
if (!entry.isPortGroupEnabled()) {
// Program the network node
public Status modifyStaticFlow(FlowConfig newFlowConfig) {
// Validity check for api3 entry point
if (newFlowConfig.isInternalFlow()) {
- String msg = "Invalid operation: Controller generated flow " +
- "cannot be modified";
- log.warn(msg);
+ String msg = "Invalid operation: Controller generated flow "
+ + "cannot be modified";
+ log.warn(msg);
return new Status(StatusCode.NOTACCEPTABLE, msg);
}
// Validity Check
StringBuffer resultStr = new StringBuffer();
if (!newFlowConfig.isValid(container, resultStr)) {
- String msg = "Invalid Configuration (" + resultStr.toString()
- + ")";
+ String msg = "Invalid Configuration (" + resultStr.toString() + ")";
newFlowConfig.setStatus(msg);
log.warn(msg);
return new Status(StatusCode.BADREQUEST, msg);
}
if (oldFlowConfig == null) {
- String msg = "Attempt to modify a non existing static flow";
- log.warn(msg);
- return new Status(StatusCode.NOTFOUND, msg);
+ String msg = "Attempt to modify a non existing static flow";
+ log.warn(msg);
+ return new Status(StatusCode.NOTFOUND, msg);
}
// Do not attempt to reinstall the flow, warn user
if (newFlowConfig.equals(oldFlowConfig)) {
- String msg = "No modification detected";
- log.info("Static flow modification skipped: " + msg);
+ String msg = "No modification detected";
+ log.info("Static flow modification skipped: " + msg);
return new Status(StatusCode.SUCCESS, msg);
}
// If flow is installed, program the network node
Status status = new Status(StatusCode.SUCCESS, "Saved in config");
if (oldFlowConfig.installInHw()) {
- status = this.modifyEntry(oldFlowConfig.getFlowEntry(),
+ status = this.modifyEntry(oldFlowConfig.getFlowEntry(),
newFlowConfig.getFlowEntry());
}
return status;
}
+ @Override
+ public Status toggleStaticFlowStatus(String name, Node node) {
+ return toggleStaticFlowStatus(getStaticFlow(name, node));
+ }
-
- @Override
- public Status toggleStaticFlowStatus(String name, Node node) {
- return toggleStaticFlowStatus(getStaticFlow(name, node));
- }
-
@Override
public Status toggleStaticFlowStatus(FlowConfig config) {
- if (config == null) {
- String msg = "Invalid request: null flow config";
- log.warn(msg);
- return new Status(StatusCode.BADREQUEST, msg);
- }
+ if (config == null) {
+ String msg = "Invalid request: null flow config";
+ log.warn(msg);
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
// Validity check for api3 entry point
if (config.isInternalFlow()) {
- String msg = "Invalid operation: Controller generated flow " +
- "cannot be modified";
- log.warn(msg);
- return new Status(StatusCode.NOTACCEPTABLE, msg);
+ String msg = "Invalid operation: Controller generated flow "
+ + "cannot be modified";
+ log.warn(msg);
+ return new Status(StatusCode.NOTACCEPTABLE, msg);
}
for (Map.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
}
}
return new Status(StatusCode.NOTFOUND,
- "Unable to locate the entry. Failed to toggle status");
+ "Unable to locate the entry. Failed to toggle status");
}
/**
- * Uninstall all the Flow Entries present in the software view
- * A copy of each entry is stored in the inactive list so
- * that it can be re-applied when needed
- * This function is called on the default container instance of FRM only
- * when the first container is created
+ * Uninstall all the Flow Entries present in the software view A copy of
+ * each entry is stored in the inactive list so that it can be re-applied
+ * when needed This function is called on the default container instance of
+ * FRM only when the first container is created
*/
private void uninstallAllFlowEntries() {
log.info("Uninstalling all flows");
for (FlowEntry flowEntry : inactiveFlows) {
Status status = this.removeEntry(flowEntry);
if (!status.isSuccess()) {
- log.warn("Failed to remove entry: {}: " +
- status.getDescription(), flowEntry);
+ log.warn(
+ "Failed to remove entry: {}: "
+ + status.getDescription(), flowEntry);
}
}
}
/**
- * Re-install all the Flow Entries present in the inactive list
- * The inactive list will be empty at the end of this call
- * This function is called on the default container instance of FRM only
- * when the last container is deleted
+ * Re-install all the Flow Entries present in the inactive list The inactive
+ * list will be empty at the end of this call This function is called on the
+ * default container instance of FRM only when the last container is deleted
*/
private void reinstallAllFlowEntries() {
log.info("Reinstalling all inactive flows");
for (FlowEntry flowEntry : this.inactiveFlows) {
- Status status = this.addEntry(flowEntry);
+ Status status = this.addEntry(flowEntry);
if (!status.isSuccess()) {
- log.warn("Failed to install entry: {}: " +
- status.getDescription(), flowEntry);
+ log.warn(
+ "Failed to install entry: {}: "
+ + status.getDescription(), flowEntry);
}
}
allowLLDP.setName("**Punt LLDP");
allowLLDP.setPriority("1");
allowLLDP.setNode(node);
- allowLLDP.setEtherType("0x"
- + Integer.toHexString(EtherTypes.LLDP.intValue())
+ allowLLDP
+ .setEtherType("0x"
+ + Integer.toHexString(EtherTypes.LLDP.intValue())
.toUpperCase());
allowLLDP.setActions(puntAction);
defaultConfigs.add(allowLLDP);
/**
* Remove from the databases all the flows installed on the node
- *
+ *
* @param node
*/
private synchronized void cleanDatabaseForNode(Node node) {
public void notifyNode(Node node, UpdateType type,
Map<String, Property> propMap) {
switch (type) {
- case ADDED:
+ case ADDED:
addStaticFlowsToSwitch(node);
break;
- case REMOVED:
+ case REMOVED:
cleanDatabaseForNode(node);
updateStaticFlowConfigsOnNodeDown(node);
break;
@Override
public void notifyNodeConnector(NodeConnector nodeConnector,
- UpdateType type, Map<String, Property> propMap) {
+ UpdateType type, Map<String, Property> propMap) {
}
private FlowConfig getDerivedFlowConfig(FlowConfig original,
@Override
public void portGroupChanged(PortGroupConfig config,
Map<Node, PortGroup> data, boolean add) {
- log.info("PortGroup Changed for :" + config + " Data: "
- + portGroupData);
+ log.info("PortGroup Changed for :" + config + " Data: " + portGroupData);
Map<Node, PortGroup> existingData = portGroupData.get(config);
if (existingData != null) {
for (Map.Entry<Node, PortGroup> entry : data.entrySet()) {
if (existingPortGroup == null) {
if (add) {
existingData.put(entry.getKey(), entry.getValue());
- addPortGroupFlows(config, entry.getKey(), entry
- .getValue());
+ addPortGroupFlows(config, entry.getKey(),
+ entry.getValue());
}
} else {
if (add) {
existingPortGroup.getPorts().addAll(
entry.getValue().getPorts());
- addPortGroupFlows(config, entry.getKey(), entry
- .getValue());
+ addPortGroupFlows(config, entry.getKey(),
+ entry.getValue());
} else {
existingPortGroup.getPorts().removeAll(
entry.getValue().getPorts());
- removePortGroupFlows(config, entry.getKey(), entry
- .getValue());
+ removePortGroupFlows(config, entry.getKey(),
+ entry.getValue());
}
}
}
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
void init() {
frmAware = Collections
.synchronizedSet(new HashSet<IForwardingRulesManagerAware>());
- frmFileName = GlobalConstants.STARTUPHOME.toString() + "frm_staticflows_"
- + this.getContainerName() + ".conf";
- portGroupFileName = GlobalConstants.STARTUPHOME.toString() + "portgroup_"
- + this.getContainerName() + ".conf";
+ frmFileName = GlobalConstants.STARTUPHOME.toString()
+ + "frm_staticflows_" + this.getContainerName() + ".conf";
+ portGroupFileName = GlobalConstants.STARTUPHOME.toString()
+ + "portgroup_" + this.getContainerName() + ".conf";
inContainerMode = false;
* Function called by the dependency manager when at least one dependency
* become unsatisfied or when the component is shutting down because for
* example bundle is being stopped.
- *
+ *
*/
void destroy() {
destroyCaches();
/**
* Function called by dependency manager after "init ()" is called and after
* the services provided by the class are registered in the service registry
- *
+ *
*/
void start() {
/*
* Function called by the dependency manager before the services exported by
* the component are unregistered, this will be followed by a "destroy ()"
* calls
- *
+ *
*/
void stop() {
}
public void containerFlowUpdated(String containerName,
ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) {
/*
- * Whether it is an addition or removal, we have to recompute the
- * merged flows entries taking into account all the current container flows
+ * Whether it is an addition or removal, we have to recompute the merged
+ * flows entries taking into account all the current container flows
* because flow merging is not an injective function
*/
updateFlowsContainerFlow();
@Override
public Status saveConfiguration() {
- return saveConfig();
+ return saveConfig();
}
public void _frmNodeFlows(CommandInterpreter ci) {
}
}
+ @Override
+ public void flowRemoved(Node node, Flow flow) {
+ log.trace("Received flow removed notification on {} for {}", node, flow);
+ // For flow entry identification, only match and priority matter
+ FlowEntry toFind = new FlowEntry("any", "any", flow, node);
+ FlowEntryInstall installedEntry = this.findMatch(toFind, false);
+ if (installedEntry == null) {
+ log.trace("Entry is not know to us");
+ return;
+ }
+
+ // Update Static flow status
+ for (Map.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+ FlowConfig conf = entry.getValue();
+ if (conf.isByNameAndNodeIdEqual(installedEntry.getFlowName(), node)) {
+ // Update Configuration database
+ conf.toggleStatus();
+ break;
+ }
+ }
+ // Update software views
+ this.updateLocalDatabase(installedEntry, false);
+ }
+
}
import java.util.List;
import java.util.Set;
+import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.protocol_plugin.openflow;
+
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
+
+/**
+ * Interface which defines the methods exposed by the Flow Programmer Notifier.
+ * Their implementation relays the asynchronous messages received from the
+ * network nodes to the the SAL Flow Programmer Notifier Service on the proper
+ * container.
+ */
+public interface IFlowProgrammerNotifier extends
+ IPluginOutFlowProgrammerService {
+
+}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.apache.felix.dm.Component;
import org.opendaylight.controller.protocol_plugin.openflow.IDataPacketListen;
import org.opendaylight.controller.protocol_plugin.openflow.IDataPacketMux;
+import org.opendaylight.controller.protocol_plugin.openflow.IFlowProgrammerNotifier;
import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExternalListener;
import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimInternalListener;
import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsManager;
import org.opendaylight.controller.protocol_plugin.openflow.IStatisticsListener;
import org.opendaylight.controller.protocol_plugin.openflow.ITopologyServiceShimListener;
import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
import org.opendaylight.controller.protocol_plugin.openflow.core.internal.Controller;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.core.IContainerListener;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.discovery.IDiscoveryService;
import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
import org.opendaylight.controller.sal.packet.IPluginInDataPacketService;
/**
* Openflow protocol plugin Activator
- *
- *
+ *
+ *
*/
public class Activator extends ComponentActivatorAbstractBase {
protected static final Logger logger = LoggerFactory
.getLogger(Activator.class);
/**
- * Function called when the activator starts just after some
- * initializations are done by the
- * ComponentActivatorAbstractBase.
- *
+ * Function called when the activator starts just after some initializations
+ * are done by the ComponentActivatorAbstractBase.
+ *
*/
public void init() {
}
/**
- * Function called when the activator stops just before the
- * cleanup done by ComponentActivatorAbstractBase
- *
+ * Function called when the activator stops just before the cleanup done by
+ * ComponentActivatorAbstractBase
+ *
*/
public void destroy() {
}
/**
- * Function that is used to communicate to dependency manager the
- * list of known implementations for services inside a container
- *
- *
+ * Function that is used to communicate to dependency manager the list of
+ * known implementations for services inside a container
+ *
+ *
* @return An array containing all the CLASS objects that will be
- * instantiated in order to get an fully working implementation
- * Object
+ * instantiated in order to get an fully working implementation
+ * Object
*/
public Object[] getImplementations() {
Object[] res = { TopologyServices.class, DataPacketServices.class,
- InventoryService.class, ReadService.class };
+ InventoryService.class, ReadService.class,
+ FlowProgrammerNotifier.class };
return res;
}
/**
- * Function that is called when configuration of the dependencies
- * is required.
- *
- * @param c dependency manager Component object, used for
- * configuring the dependencies exported and imported
- * @param imp Implementation class that is being configured,
- * needed as long as the same routine can configure multiple
- * implementations
- * @param containerName The containerName being configured, this allow
- * also optional per-container different behavior if needed, usually
- * should not be the case though.
+ * Function that is called when configuration of the dependencies is
+ * required.
+ *
+ * @param c
+ * dependency manager Component object, used for configuring the
+ * dependencies exported and imported
+ * @param imp
+ * Implementation class that is being configured, needed as long
+ * as the same routine can configure multiple implementations
+ * @param containerName
+ * The containerName being configured, this allow also optional
+ * per-container different behavior if needed, usually should not
+ * be the case though.
*/
public void configureInstance(Component c, Object imp, String containerName) {
if (imp.equals(TopologyServices.class)) {
// export the service to be used by SAL
- c.setInterface(new String[] {
- IPluginInTopologyService.class.getName(),
- ITopologyServiceShimListener.class.getName() }, null);
+ c.setInterface(
+ new String[] { IPluginInTopologyService.class.getName(),
+ ITopologyServiceShimListener.class.getName() },
+ null);
// Hook the services coming in from SAL, as optional in
// case SAL is not yet there, could happen
- c.add(createContainerServiceDependency(containerName).setService(
- IPluginOutTopologyService.class).setCallbacks(
- "setPluginOutTopologyService",
- "unsetPluginOutTopologyService").setRequired(false));
- c.add(createServiceDependency().setService(
- IRefreshInternalProvider.class).setCallbacks(
- "setRefreshInternalProvider",
- "unsetRefreshInternalProvider").setRequired(false));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginOutTopologyService.class)
+ .setCallbacks("setPluginOutTopologyService",
+ "unsetPluginOutTopologyService").setRequired(false));
+ c.add(createServiceDependency()
+ .setService(IRefreshInternalProvider.class)
+ .setCallbacks("setRefreshInternalProvider",
+ "unsetRefreshInternalProvider").setRequired(false));
}
if (imp.equals(InventoryService.class)) {
// export the service
- c.setInterface(new String[] {
- IPluginInInventoryService.class.getName(),
- IStatisticsListener.class.getName(),
- IInventoryShimInternalListener.class.getName() }, null);
+ c.setInterface(
+ new String[] { IPluginInInventoryService.class.getName(),
+ IStatisticsListener.class.getName(),
+ IInventoryShimInternalListener.class.getName() },
+ null);
// Now lets add a service dependency to make sure the
// provider of service exists
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
- c.add(createContainerServiceDependency(containerName).setService(
- IPluginOutInventoryService.class).setCallbacks(
- "setPluginOutInventoryServices",
- "unsetPluginOutInventoryServices").setRequired(false));
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginOutInventoryService.class)
+ .setCallbacks("setPluginOutInventoryServices",
+ "unsetPluginOutInventoryServices")
+ .setRequired(false));
}
if (imp.equals(DataPacketServices.class)) {
c.setInterface(IPluginInDataPacketService.class.getName(), props);
// Hook the services coming in from SAL, as optional in
// case SAL is not yet there, could happen
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
// This is required for the transmission to happen properly
c.add(createServiceDependency().setService(IDataPacketMux.class)
.setCallbacks("setIDataPacketMux", "unsetIDataPacketMux")
.setRequired(true));
- c.add(createContainerServiceDependency(containerName).setService(
- IPluginOutDataPacketService.class).setCallbacks(
- "setPluginOutDataPacketService",
- "unsetPluginOutDataPacketService").setRequired(false));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginOutDataPacketService.class)
+ .setCallbacks("setPluginOutDataPacketService",
+ "unsetPluginOutDataPacketService")
+ .setRequired(false));
}
if (imp.equals(ReadService.class)) {
// by SAL
props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
c.setInterface(IPluginInReadService.class.getName(), props);
- c.add(createServiceDependency().setService(
- IPluginReadServiceFilter.class).setCallbacks("setService",
- "unsetService").setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IPluginReadServiceFilter.class)
+ .setCallbacks("setService", "unsetService")
+ .setRequired(true));
+ }
+
+ if (imp.equals(FlowProgrammerNotifier.class)) {
+ // export the service to be used by SAL
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ // Set the protocolPluginType property which will be used
+ // by SAL
+ props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+ c.setInterface(IFlowProgrammerNotifier.class.getName(), props);
+
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginOutFlowProgrammerService.class)
+ .setCallbacks("setPluginOutFlowProgrammerService",
+ "unsetPluginOutFlowProgrammerService")
+ .setRequired(true));
}
}
/**
- * Function that is used to communicate to dependency manager the
- * list of known implementations for services that are container
- * independent.
- *
- *
+ * Function that is used to communicate to dependency manager the list of
+ * known implementations for services that are container independent.
+ *
+ *
* @return An array containing all the CLASS objects that will be
- * instantiated in order to get an fully working implementation
- * Object
+ * instantiated in order to get an fully working implementation
+ * Object
*/
public Object[] getGlobalImplementations() {
Object[] res = { Controller.class, OFStatisticsManager.class,
}
/**
- * Function that is called when configuration of the dependencies
- * is required.
- *
- * @param c dependency manager Component object, used for
- * configuring the dependencies exported and imported
- * @param imp Implementation class that is being configured,
- * needed as long as the same routine can configure multiple
- * implementations
+ * Function that is called when configuration of the dependencies is
+ * required.
+ *
+ * @param c
+ * dependency manager Component object, used for configuring the
+ * dependencies exported and imported
+ * @param imp
+ * Implementation class that is being configured, needed as long
+ * as the same routine can configure multiple implementations
*/
public void configureGlobalInstance(Component c, Object imp) {
// Set the protocolPluginType property which will be used
// by SAL
props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
- c.setInterface(IPluginInFlowProgrammerService.class
- .getName(), props);
+ c.setInterface(
+ new String[] {
+ IPluginInFlowProgrammerService.class.getName(),
+ IMessageListener.class.getName(),
+ IContainerListener.class.getName() }, props);
+
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
+
+ c.add(createServiceDependency()
+ .setService(IFlowProgrammerNotifier.class)
+ .setCallbacks("setFlowProgrammerNotifier",
+ "unsetsetFlowProgrammerNotifier")
+ .setRequired(false));
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
}
if (imp.equals(ReadServiceFilter.class)) {
- c.setInterface(new String[] {
- IPluginReadServiceFilter.class.getName(),
- IContainerListener.class.getName() }, null);
+ c.setInterface(
+ new String[] { IPluginReadServiceFilter.class.getName(),
+ IContainerListener.class.getName() }, null);
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
- c.add(createServiceDependency().setService(
- IOFStatisticsManager.class).setCallbacks("setService",
- "unsetService").setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IOFStatisticsManager.class)
+ .setCallbacks("setService", "unsetService")
+ .setRequired(true));
}
if (imp.equals(OFStatisticsManager.class)) {
c.setInterface(new String[] { IOFStatisticsManager.class.getName(),
IInventoryShimExternalListener.class.getName() }, null);
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
- c.add(createServiceDependency().setService(
- IStatisticsListener.class)
- .setCallbacks("setStatisticsListener",
- "unsetStatisticsListener").setRequired(false));
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IStatisticsListener.class)
+ .setCallbacks("setStatisticsListener",
+ "unsetStatisticsListener").setRequired(false));
}
if (imp.equals(DiscoveryService.class)) {
// export the service
- c.setInterface(new String[] {
- IInventoryShimExternalListener.class.getName(),
- IDataPacketListen.class.getName(),
- IContainerListener.class.getName() }, null);
-
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
+ c.setInterface(
+ new String[] {
+ IInventoryShimExternalListener.class.getName(),
+ IDataPacketListen.class.getName(),
+ IContainerListener.class.getName() }, null);
+
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
c.add(createContainerServiceDependency(
- GlobalConstants.DEFAULT.toString()).setService(
- IPluginInInventoryService.class).setCallbacks(
- "setPluginInInventoryService",
- "unsetPluginInInventoryService").setRequired(true));
+ GlobalConstants.DEFAULT.toString())
+ .setService(IPluginInInventoryService.class)
+ .setCallbacks("setPluginInInventoryService",
+ "unsetPluginInInventoryService").setRequired(true));
c.add(createServiceDependency().setService(IDataPacketMux.class)
.setCallbacks("setIDataPacketMux", "unsetIDataPacketMux")
.setRequired(true));
- c.add(createServiceDependency().setService(IDiscoveryService.class)
+ c.add(createServiceDependency()
+ .setService(IDiscoveryService.class)
.setCallbacks("setDiscoveryService",
"unsetDiscoveryService").setRequired(true));
}
IContainerListener.class.getName(),
IInventoryShimExternalListener.class.getName() }, null);
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
- c.add(createServiceDependency().setService(
- IPluginOutDataPacketService.class).setCallbacks(
- "setPluginOutDataPacketService",
- "unsetPluginOutDataPacketService").setRequired(false));
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IPluginOutDataPacketService.class)
+ .setCallbacks("setPluginOutDataPacketService",
+ "unsetPluginOutDataPacketService")
+ .setRequired(false));
// See if there is any local packet dispatcher
- c.add(createServiceDependency().setService(IDataPacketListen.class)
+ c.add(createServiceDependency()
+ .setService(IDataPacketListen.class)
.setCallbacks("setIDataPacketListen",
"unsetIDataPacketListen").setRequired(false));
}
c.setInterface(new String[] { IContainerListener.class.getName() },
null);
- c.add(createServiceDependency().setService(IController.class,
- "(name=Controller)").setCallbacks("setController",
- "unsetController").setRequired(true));
- c.add(createServiceDependency().setService(
- IInventoryShimInternalListener.class).setCallbacks(
- "setInventoryShimInternalListener",
- "unsetInventoryShimInternalListener").setRequired(true));
- c.add(createServiceDependency().setService(
- IInventoryShimExternalListener.class).setCallbacks(
- "setInventoryShimExternalListener",
- "unsetInventoryShimExternalListener").setRequired(false));
+ c.add(createServiceDependency()
+ .setService(IController.class, "(name=Controller)")
+ .setCallbacks("setController", "unsetController")
+ .setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IInventoryShimInternalListener.class)
+ .setCallbacks("setInventoryShimInternalListener",
+ "unsetInventoryShimInternalListener")
+ .setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IInventoryShimExternalListener.class)
+ .setCallbacks("setInventoryShimExternalListener",
+ "unsetInventoryShimExternalListener")
+ .setRequired(false));
}
if (imp.equals(TopologyServiceShim.class)) {
c.setInterface(new String[] { IDiscoveryService.class.getName(),
IContainerListener.class.getName(),
IRefreshInternalProvider.class.getName() }, null);
- c.add(createServiceDependency().setService(
- ITopologyServiceShimListener.class).setCallbacks(
- "setTopologyServiceShimListener",
- "unsetTopologyServiceShimListener").setRequired(true));
- c.add(createServiceDependency().setService(
- IOFStatisticsManager.class).setCallbacks(
- "setStatisticsManager", "unsetStatisticsManager")
- .setRequired(false));
+ c.add(createServiceDependency()
+ .setService(ITopologyServiceShimListener.class)
+ .setCallbacks("setTopologyServiceShimListener",
+ "unsetTopologyServiceShimListener")
+ .setRequired(true));
+ c.add(createServiceDependency()
+ .setService(IOFStatisticsManager.class)
+ .setCallbacks("setStatisticsManager",
+ "unsetStatisticsManager").setRequired(false));
}
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* Utility class for converting a SAL Flow into the OF flow and vice-versa
- *
- *
- *
*/
public class FlowConverter {
private Flow flow; // SAL Flow
}
/**
- * Returns the match in OF 1.0 (OFMatch) form or OF 1.0 + IPv6 extensions form (V6Match)
- *
+ * Returns the match in OF 1.0 (OFMatch) form or OF 1.0 + IPv6 extensions
+ * form (V6Match)
+ *
* @return
*/
public OFMatch getOFMatch() {
}
if (match.isPresent(MatchType.NW_TOS)) {
/*
- * OF 1.0 switch expects the TOS as the 6 msb in the byte.
- * it is actually the DSCP field followed by a zero ECN
+ * OF 1.0 switch expects the TOS as the 6 msb in the byte. it is
+ * actually the DSCP field followed by a zero ECN
*/
byte tos = (Byte) match.getField(MatchType.NW_TOS).getValue();
- byte dscp = (byte)((int)tos << 2);
+ byte dscp = (byte) ((int) tos << 2);
if (!isIPv6) {
ofMatch.setNetworkTypeOfService(dscp);
wildcards &= ~OFMatch.OFPFW_NW_TOS;
/**
* Returns the list of actions in OF 1.0 form
+ *
* @return
*/
public List<OFAction> getOFActions() {
if (action.getType() == ActionType.CONTROLLER) {
OFActionOutput ofAction = new OFActionOutput();
ofAction.setPort(OFPort.OFPP_CONTROLLER.getValue());
- // We want the whole frame hitting the match be sent to the controller
+ // We want the whole frame hitting the match be sent to the
+ // controller
ofAction.setMaxLength((short) 0xffff);
actionsList.add(ofAction);
actionsLength += OFActionOutput.MINIMUM_LENGTH;
continue;
}
if (action.getType() == ActionType.SET_NEXT_HOP) {
- //TODO
+ // TODO
continue;
}
}
}
/**
- * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or
- * to an OF 1.0 + IPv6 extension (V6FlowMod) Flow modifier Message
- *
+ * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or to an OF 1.0 +
+ * IPv6 extension (V6FlowMod) Flow modifier Message
+ *
* @param sw
* @param command
* @param port
if (port != null) {
((OFFlowMod) fm).setOutPort(port);
}
+ if (command == OFFlowMod.OFPFC_ADD
+ || command == OFFlowMod.OFPFC_MODIFY
+ || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
+ if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) {
+ // Instruct switch to let controller know when flow expires
+ ((OFFlowMod) fm).setFlags((short) 1);
+ }
+ }
} else {
((V6FlowMod) fm).setVendor();
((V6FlowMod) fm).setMatch((V6Match) ofMatch);
if (port != null) {
((V6FlowMod) fm).setOutPort(port);
}
+ if (command == OFFlowMod.OFPFC_ADD
+ || command == OFFlowMod.OFPFC_MODIFY
+ || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
+ if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) {
+ // Instruct switch to let controller know when flow expires
+ ((V6FlowMod) fm).setFlags((short) 1);
+ }
+ }
}
return fm;
}
Match salMatch = new Match();
/*
- * Installed flow may not have a Match defined
- * like in case of a drop all flow
+ * Installed flow may not have a Match defined like in case of a
+ * drop all flow
*/
if (ofMatch != null) {
if (!isIPv6) {
if (ofMatch.getNetworkSource() != 0) {
salMatch.setField(MatchType.NW_SRC, NetUtils
.getInetAddress(ofMatch.getNetworkSource()),
- NetUtils.getInetNetworkMask(ofMatch
- .getNetworkSourceMaskLen(), false));
+ NetUtils.getInetNetworkMask(
+ ofMatch.getNetworkSourceMaskLen(),
+ false));
}
if (ofMatch.getNetworkDestination() != 0) {
- salMatch
- .setField(
- MatchType.NW_DST,
- NetUtils.getInetAddress(ofMatch
- .getNetworkDestination()),
- NetUtils
- .getInetNetworkMask(
- ofMatch
- .getNetworkDestinationMaskLen(),
- false));
+ salMatch.setField(MatchType.NW_DST,
+ NetUtils.getInetAddress(ofMatch
+ .getNetworkDestination()),
+ NetUtils.getInetNetworkMask(
+ ofMatch.getNetworkDestinationMaskLen(),
+ false));
}
if (ofMatch.getNetworkTypeOfService() != 0) {
- int dscp = NetUtils.getUnsignedByte(
- ofMatch.getNetworkTypeOfService());
- byte tos = (byte)(dscp >> 2);
+ int dscp = NetUtils.getUnsignedByte(ofMatch
+ .getNetworkTypeOfService());
+ byte tos = (byte) (dscp >> 2);
salMatch.setField(MatchType.NW_TOS, tos);
}
if (ofMatch.getNetworkProtocol() != 0) {
- salMatch.setField(MatchType.NW_PROTO, ofMatch
- .getNetworkProtocol());
+ salMatch.setField(MatchType.NW_PROTO,
+ ofMatch.getNetworkProtocol());
}
if (ofMatch.getTransportSource() != 0) {
- salMatch.setField(MatchType.TP_SRC, ((Short) ofMatch
- .getTransportSource()));
+ salMatch.setField(MatchType.TP_SRC,
+ ((Short) ofMatch.getTransportSource()));
}
if (ofMatch.getTransportDestination() != 0) {
- salMatch.setField(MatchType.TP_DST, ((Short) ofMatch
- .getTransportDestination()));
+ salMatch.setField(MatchType.TP_DST,
+ ((Short) ofMatch.getTransportDestination()));
}
} else {
// Compute OF1.0 + IPv6 extensions Match
.getDataLayerVirtualLanPriorityCodePoint());
}
if (v6Match.getNetworkSrc() != null) {
- salMatch.setField(MatchType.NW_SRC, v6Match
- .getNetworkSrc(), v6Match
- .getNetworkSourceMask());
+ salMatch.setField(MatchType.NW_SRC,
+ v6Match.getNetworkSrc(),
+ v6Match.getNetworkSourceMask());
}
if (v6Match.getNetworkDest() != null) {
- salMatch.setField(MatchType.NW_DST, v6Match
- .getNetworkDest(), v6Match
- .getNetworkDestinationMask());
+ salMatch.setField(MatchType.NW_DST,
+ v6Match.getNetworkDest(),
+ v6Match.getNetworkDestinationMask());
}
if (v6Match.getNetworkTypeOfService() != 0) {
- int dscp = NetUtils.getUnsignedByte(
- v6Match.getNetworkTypeOfService());
- byte tos = (byte) (dscp >> 2);
+ int dscp = NetUtils.getUnsignedByte(v6Match
+ .getNetworkTypeOfService());
+ byte tos = (byte) (dscp >> 2);
salMatch.setField(MatchType.NW_TOS, tos);
}
if (v6Match.getNetworkProtocol() != 0) {
- salMatch.setField(MatchType.NW_PROTO, v6Match
- .getNetworkProtocol());
+ salMatch.setField(MatchType.NW_PROTO,
+ v6Match.getNetworkProtocol());
}
if (v6Match.getTransportSource() != 0) {
- salMatch.setField(MatchType.TP_SRC, ((Short) v6Match
- .getTransportSource()));
+ salMatch.setField(MatchType.TP_SRC,
+ ((Short) v6Match.getTransportSource()));
}
if (v6Match.getTransportDestination() != 0) {
- salMatch.setField(MatchType.TP_DST, ((Short) v6Match
- .getTransportDestination()));
+ salMatch.setField(MatchType.TP_DST,
+ ((Short) v6Match.getTransportDestination()));
}
}
}
} else if (ofPort == OFPort.OFPP_NORMAL.getValue()) {
salAction = new HwPath();
} else if (ofPort == OFPort.OFPP_TABLE.getValue()) {
- salAction = new HwPath(); //TODO: we do not handle table in sal for now
+ salAction = new HwPath(); // TODO: we do not handle
+ // table in sal for now
} else {
- salAction = new Output(NodeConnectorCreator
- .createOFNodeConnector(ofPort, node));
+ salAction = new Output(
+ NodeConnectorCreator.createOFNodeConnector(
+ ofPort, node));
}
} else if (ofAction instanceof OFActionVirtualLanIdentifier) {
salAction = new SetVlanId(
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.protocol_plugin.openflow.internal;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.protocol_plugin.openflow.IFlowProgrammerNotifier;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Flow Programmer Notifier class for relaying asynchronous messages received
+ * from the network node to the listeners on the proper container
+ */
+public class FlowProgrammerNotifier implements IFlowProgrammerNotifier {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(FlowProgrammerNotifier.class);
+ private IPluginOutFlowProgrammerService salNotifier;
+
+ public FlowProgrammerNotifier() {
+ salNotifier = null;
+ }
+
+ void init(Component c) {
+ logger.debug("INIT called!");
+ }
+
+ /**
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ logger.debug("DESTROY called!");
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ void start() {
+ logger.debug("START called!");
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ void stop() {
+ logger.debug("STOP called!");
+ }
+
+ public void setPluginOutFlowProgrammerService(
+ IPluginOutFlowProgrammerService s) {
+ this.salNotifier = s;
+ }
+
+ public void unsetPluginOutFlowProgrammerService(
+ IPluginOutFlowProgrammerService s) {
+ if (this.salNotifier == s) {
+ this.salNotifier = null;
+ }
+ }
+
+ @Override
+ public void flowRemoved(Node node, Flow flow) {
+ if (salNotifier != null) {
+ salNotifier.flowRemoved(node, flow);
+ } else {
+ logger.warn("Unable to relay switch message to upper layer");
+ }
+ }
+
+}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
package org.opendaylight.controller.protocol_plugin.openflow.internal;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.protocol_plugin.openflow.IFlowProgrammerNotifier;
import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error;
import org.openflow.protocol.OFError;
import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFFlowRemoved;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.IContainerListener;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.UpdateType;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.NodeCreator;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.sal.utils.Status;
import org.slf4j.Logger;
/**
* Represents the openflow plugin component in charge of programming the flows
- * on the switch. It servers the install requests coming from the SAL layer.
- *
- *
- *
+ * the flow programming and relay them to functional modules above SAL.
*/
-public class FlowProgrammerService implements IPluginInFlowProgrammerService {
- private static final Logger log = LoggerFactory
- .getLogger(FlowProgrammerService.class);
+public class FlowProgrammerService implements IPluginInFlowProgrammerService,
+ IMessageListener, IContainerListener {
+ private static final Logger log = LoggerFactory
+ .getLogger(FlowProgrammerService.class);
private IController controller;
+ private ConcurrentMap<String, IFlowProgrammerNotifier> flowProgrammerNotifiers;
+ private Map<String, Set<NodeConnector>> containerToNc;
public FlowProgrammerService() {
controller = null;
+ flowProgrammerNotifiers = new ConcurrentHashMap<String, IFlowProgrammerNotifier>();
}
public void setController(IController core) {
}
}
+ public void setFlowProgrammerNotifier(Map<String, ?> props,
+ IFlowProgrammerNotifier s) {
+ if (props == null || props.get("containerName") == null) {
+ log.error("Didn't receive the service correct properties");
+ return;
+ }
+ String containerName = (String) props.get("containerName");
+ this.flowProgrammerNotifiers.put(containerName, s);
+ }
+
+ public void unsetFlowProgrammerNotifier(Map<String, ?> props,
+ IFlowProgrammerNotifier s) {
+ if (props == null || props.get("containerName") == null) {
+ log.error("Didn't receive the service correct properties");
+ return;
+ }
+ String containerName = (String) props.get("containerName");
+ if (this.flowProgrammerNotifiers != null
+ && this.flowProgrammerNotifiers.containsKey(containerName)
+ && this.flowProgrammerNotifiers.get(containerName) == s) {
+ this.flowProgrammerNotifiers.remove(containerName);
+ }
+ }
+
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
void init() {
+ this.controller.addMessageListener(OFType.FLOW_REMOVED, this);
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
- *
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
*/
void destroy() {
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
- *
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
*/
void start() {
}
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
- *
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
*/
void stop() {
}
public Status addFlow(Node node, Flow flow) {
String action = "add";
if (!node.getType().equals(NodeIDType.OPENFLOW)) {
- return new Status(StatusCode.NOTACCEPTABLE,
- errorString("send", action, "Invalid node type"));
+ return new Status(StatusCode.NOTACCEPTABLE, errorString("send",
+ action, "Invalid node type"));
}
if (controller != null) {
*/
Object result = sw.syncSend(msg);
if (result instanceof Boolean) {
- return ((Boolean) result == Boolean.TRUE) ?
- new Status(StatusCode.SUCCESS, null)
- : new Status(StatusCode.TIMEOUT,
- errorString(null, action,
- "Request Timed Out"));
+ return ((Boolean) result == Boolean.TRUE) ? new Status(
+ StatusCode.SUCCESS, null) : new Status(
+ StatusCode.TIMEOUT, errorString(null, action,
+ "Request Timed Out"));
} else if (result instanceof OFError) {
- OFError res = (OFError) result;
- if (res.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) {
- V6Error er = new V6Error(res);
- byte[] b = res.getError();
- ByteBuffer bb = ByteBuffer.allocate(b.length);
- bb.put(b);
- bb.rewind();
- er.readFrom(bb);
- log.trace("V6Error {}",er);
- return new Status(StatusCode.INTERNALERROR,
- errorString("program", action, "Vendor Extension Internal Error"));
- }
- return new Status(StatusCode.INTERNALERROR,
- errorString("program", action, Utils
- .getOFErrorString(res)));
+ OFError res = (OFError) result;
+ if (res.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) {
+ V6Error er = new V6Error(res);
+ byte[] b = res.getError();
+ ByteBuffer bb = ByteBuffer.allocate(b.length);
+ bb.put(b);
+ bb.rewind();
+ er.readFrom(bb);
+ return new Status(StatusCode.INTERNALERROR,
+ errorString("program", action,
+ "Vendor Extension Internal Error"));
+ }
+ return new Status(StatusCode.INTERNALERROR, errorString(
+ "program", action, Utils.getOFErrorString(res)));
} else {
- return new Status(StatusCode.INTERNALERROR,
- errorString("send", action, "Internal Error"));
+ return new Status(StatusCode.INTERNALERROR, errorString(
+ "send", action, "Internal Error"));
}
} else {
return new Status(StatusCode.GONE, errorString("send", action,
- "Switch is not available"));
+ "Switch is not available"));
}
}
- return new Status(StatusCode.INTERNALERROR,
- errorString("send", action, "Internal plugin error"));
+ return new Status(StatusCode.INTERNALERROR, errorString("send", action,
+ "Internal plugin error"));
}
@Override
public Status modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
String action = "modify";
if (!node.getType().equals(NodeIDType.OPENFLOW)) {
- return new Status(StatusCode.NOTACCEPTABLE,
- errorString("send", action, "Invalid node type"));
+ return new Status(StatusCode.NOTACCEPTABLE, errorString("send",
+ action, "Invalid node type"));
}
if (controller != null) {
ISwitch sw = controller.getSwitch((Long) node.getID());
if (sw != null) {
OFMessage msg1 = null, msg2 = null;
- // If priority and match portion are the same, send a modification message
+ // If priority and match portion are the same, send a
+ // modification message
if (oldFlow.getPriority() != newFlow.getPriority()
|| !oldFlow.getMatch().equals(newFlow.getMatch())) {
msg1 = new FlowConverter(oldFlow).getOFFlowMod(
Object result = sw.syncSend(msg1);
if (result instanceof Boolean) {
if ((Boolean) result == Boolean.FALSE) {
- return new Status(StatusCode.TIMEOUT,
- errorString(null, action,
- "Request Timed Out"));
+ return new Status(StatusCode.TIMEOUT, errorString(null,
+ action, "Request Timed Out"));
} else if (msg2 == null) {
return new Status(StatusCode.SUCCESS, null);
}
} else if (result instanceof OFError) {
- return new Status(StatusCode.INTERNALERROR,
- errorString("program", action, Utils
- .getOFErrorString((OFError) result)));
+ return new Status(StatusCode.INTERNALERROR, errorString(
+ "program", action,
+ Utils.getOFErrorString((OFError) result)));
} else {
- return new Status(StatusCode.INTERNALERROR,
- errorString("send", action, "Internal Error"));
+ return new Status(StatusCode.INTERNALERROR, errorString(
+ "send", action, "Internal Error"));
}
if (msg2 != null) {
action = "add";
result = sw.syncSend(msg2);
if (result instanceof Boolean) {
- return ((Boolean) result == Boolean.TRUE) ?
- new Status(StatusCode.SUCCESS, null)
- : new Status(StatusCode.TIMEOUT,
- errorString(null, action,
- "Request Timed Out"));
+ return ((Boolean) result == Boolean.TRUE) ? new Status(
+ StatusCode.SUCCESS, null) : new Status(
+ StatusCode.TIMEOUT, errorString(null, action,
+ "Request Timed Out"));
} else if (result instanceof OFError) {
return new Status(StatusCode.INTERNALERROR,
errorString("program", action, Utils
- .getOFErrorString((OFError) result)));
+ .getOFErrorString((OFError) result)));
} else {
return new Status(StatusCode.INTERNALERROR,
errorString("send", action, "Internal Error"));
"Switch is not available"));
}
}
- return new Status(StatusCode.INTERNALERROR,
- errorString("send", action, "Internal plugin error"));
+ return new Status(StatusCode.INTERNALERROR, errorString("send", action,
+ "Internal plugin error"));
}
@Override
public Status removeFlow(Node node, Flow flow) {
String action = "remove";
if (!node.getType().equals(NodeIDType.OPENFLOW)) {
- return new Status(StatusCode.NOTACCEPTABLE,
- errorString("send", action, "Invalid node type"));
+ return new Status(StatusCode.NOTACCEPTABLE, errorString("send",
+ action, "Invalid node type"));
}
if (controller != null) {
ISwitch sw = controller.getSwitch((Long) node.getID());
OFFlowMod.OFPFC_DELETE_STRICT, OFPort.OFPP_NONE);
Object result = sw.syncSend(msg);
if (result instanceof Boolean) {
- return ((Boolean) result == Boolean.TRUE) ?
- new Status(StatusCode.SUCCESS, null)
- : new Status(StatusCode.TIMEOUT,
- errorString(null, action,
- "Request Timed Out"));
+ return ((Boolean) result == Boolean.TRUE) ? new Status(
+ StatusCode.SUCCESS, null) : new Status(
+ StatusCode.TIMEOUT, errorString(null, action,
+ "Request Timed Out"));
} else if (result instanceof OFError) {
- return new Status(StatusCode.INTERNALERROR,
- errorString("program", action, Utils
- .getOFErrorString((OFError) result)));
+ return new Status(StatusCode.INTERNALERROR, errorString(
+ "program", action,
+ Utils.getOFErrorString((OFError) result)));
} else {
- return new Status(StatusCode.INTERNALERROR,
- errorString("send", action, "Internal Error"));
+ return new Status(StatusCode.INTERNALERROR, errorString(
+ "send", action, "Internal Error"));
}
} else {
- return new Status(StatusCode.GONE, errorString("send", action,
+ return new Status(StatusCode.GONE, errorString("send", action,
"Switch is not available"));
}
}
- return new Status(StatusCode.INTERNALERROR,
- errorString("send", action, "Internal plugin error"));
+ return new Status(StatusCode.INTERNALERROR, errorString("send", action,
+ "Internal plugin error"));
}
@Override
+ " flow message: " : action + " the flow: ") + cause;
}
+ @Override
+ public void receive(ISwitch sw, OFMessage msg) {
+ if (msg instanceof OFFlowRemoved) {
+ handleFlowRemovedMessage(sw, (OFFlowRemoved) msg);
+ }
+ }
+
+ private void handleFlowRemovedMessage(ISwitch sw, OFFlowRemoved msg) {
+ Node node = NodeCreator.createOFNode(sw.getId());
+ Flow flow = new FlowConverter(msg.getMatch(),
+ new ArrayList<OFAction>(0)).getFlow(node);
+ flow.setPriority(msg.getPriority());
+ flow.setIdleTimeout(msg.getIdleTimeout());
+ flow.setId(msg.getCookie());
+
+ Match match = flow.getMatch();
+ NodeConnector inPort = match.isPresent(MatchType.IN_PORT) ? (NodeConnector) match
+ .getField(MatchType.IN_PORT).getValue() : null;
+
+ for (Map.Entry<String, IFlowProgrammerNotifier> containerNotifier : flowProgrammerNotifiers
+ .entrySet()) {
+ String container = containerNotifier.getKey();
+ IFlowProgrammerNotifier notifier = containerNotifier.getValue();
+ /*
+ * Switch only provide us with the match information. For now let's
+ * try to identify the container membership only from the input port
+ * match field. In any case, upper layer consumers can derive
+ * whether the notification was not for them. More sophisticated
+ * filtering can be added later on.
+ */
+ if (inPort == null
+ || container.equals(GlobalConstants.DEFAULT.toString())
+ || this.containerToNc.get(container).contains(inPort)) {
+ notifier.flowRemoved(node, flow);
+ }
+ }
+ }
+
+ @Override
+ public void tagUpdated(String containerName, Node n, short oldTag,
+ short newTag, UpdateType t) {
+
+ }
+
+ @Override
+ public void containerFlowUpdated(String containerName,
+ ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) {
+ }
+
+ @Override
+ public void nodeConnectorUpdated(String containerName, NodeConnector p,
+ UpdateType type) {
+ Set<NodeConnector> target = null;
+
+ switch (type) {
+ case ADDED:
+ if (!containerToNc.containsKey(containerName)) {
+ containerToNc.put(containerName, new HashSet<NodeConnector>());
+ }
+ containerToNc.get(containerName).add(p);
+ break;
+ case CHANGED:
+ break;
+ case REMOVED:
+ target = containerToNc.get(containerName);
+ if (target != null) {
+ target.remove(p);
+ }
+ break;
+ default:
+ }
+
+ }
+
+ @Override
+ public void containerModeUpdated(UpdateType t) {
+
+ }
}
.getLast());
long timePeriod = (long) (factoredSamples * portStatsPeriod)
/ (long) tickPeriod;
- average = (8 * increment) / timePeriod;
+ average = (8L * increment) / timePeriod;
return average;
}
}
import java.util.LinkedList;
import java.util.List;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.openflow.protocol.OFPacketOut;
import org.openflow.protocol.OFPort;
import org.openflow.protocol.OFVendor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
-
/**
* This class is used to create IPv6 Vendor Extension messages. Specfically, It
* defines the methods used in creation of Vendor specific IPv6 Flow Mod message.
super.setVendor(V6StatsRequest.NICIRA_VENDOR_ID);
}
+ /**
+ * Get flags
+ * @return
+ */
+ public short getFlags() {
+ return flags;
+ }
+
+ /**
+ * Set flags
+ * @param flags
+ */
+ public void setFlags(short flags) {
+ this.flags = flags;
+ }
+
/**
* This method forms the Vendor extension IPv6 Flow Mod message.It uses the
* fields in V6FlowMod class, and writes the data according to vendor
data.putShort(this.priority);
data.putInt(OFPacketOut.BUFFER_ID_NONE);
data.putShort(outPort); /* output_port */
- data.putShort((short) 0); /* flags */
+ data.putShort(flags); /* flags */
match_len = this.match.getIPv6MatchLen();
data.putShort(match_len);
byte[] pad = new byte[6];
* Interface for applications which maintain an authorization
* database for their resources. Respective application web bundle
* and User Manager make use of this interface to retrieve
- * authorization information at user or and role level
+ * authorization information at user or and role level.
*/
public interface IResourceAuthorization {
public List<String> getResourceGroups();
/**
- * Assign a resource group to a user group (role)
+ * Assign a resource group to a role
*
- * @param groupName the object expressing the resource group name and the access privilege
- * @param role the user group (role) name
+ * @param groupName the name of the resource group
+ * @param privilege the access privilege role will have on the resource group
+ * @param role the role name
* @return the status of the request
*/
+ @Deprecated
public Status assignResourceGroupToRole(String groupName,
Privilege privilege, String role);
+ /**
+ * Assign a resource group to a role. The access privilege on the resources
+ * is inferred by the AppRoleLevel associated to role.
+ *
+ * @param groupName the name of the resource group
+ * @param role the role name
+ * @return the status of the request
+ */
+ public Status assignResourceGroupToRole(String groupName, String role);
+
/**
* Unassign the passed resource group from the specified role
*
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.flowprogrammer;
+
+/**
+ * This interface defines the methods the SAL service which relay to the
+ * functional modules the asynchronous messages related to flow programming
+ * coming from the network nodes.
+ */
+public interface IFlowProgrammerListener extends
+ IPluginOutFlowProgrammerService {
+
+}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.opendaylight.controller.sal.utils.Status;
/**
- * Interface for installing/removing flows on a network node
- *
- *
- *
+ * Interface that defines the methods available to the functional modules above
+ * SAL for installing/modifying/removing flows on a network node
*/
public interface IFlowProgrammerService {
/**
* Add a flow to the network node
- *
+ *
* @param node
* @param flow
*/
/**
* Modify existing flow on the switch
- *
+ *
* @param node
* @param flow
*/
/**
* Remove the flow from the network node
+ *
* @param node
* @param flow
*/
/**
* Remove all flows present on the network node
+ *
* @param node
*/
Status removeAllFlows(Node node);
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.opendaylight.controller.sal.utils.Status;
/**
- * @file IPluginOutFlowProgrammer.java
- *
- * @brief Flow programmer interface to be implemented by protocol plugins
- *
- *
- *
+ * @file IPluginOutFlowProgrammer.java
+ *
+ * @brief Flow programmer interface to be implemented by protocol plugins
*/
public interface IPluginInFlowProgrammerService {
/**
* Add a flow to the network node
- *
+ *
* @param node
* @param flow
*/
- Status addFlow(Node node, Flow flow);
+ Status addFlow(Node node, Flow flow);
/**
* Modify existing flow on the switch
- *
+ *
* @param node
* @param flow
*/
- Status modifyFlow(Node node, Flow oldFlow, Flow newFlow);
+ Status modifyFlow(Node node, Flow oldFlow, Flow newFlow);
/**
* Remove the flow from the network node
+ *
* @param node
* @param flow
*/
- Status removeFlow(Node node, Flow flow);
+ Status removeFlow(Node node, Flow flow);
/**
* Remove all flows present on the network node
+ *
* @param node
*/
- Status removeAllFlows(Node node);
+ Status removeAllFlows(Node node);
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.flowprogrammer;
+
+import org.opendaylight.controller.sal.core.Node;
+
+/**
+ * This interface defines the methods the protocol plugin must implement to
+ * inform the SAL layer about the asynchronous messages related to flow
+ * programming coming from the network nodes.
+ */
+public interface IPluginOutFlowProgrammerService {
+ /**
+ * Inform SAL that the flow on the specified node has been removed Consumer
+ * has to expect this notification only for flows which were installed with
+ * an idle or hard timeout specified.
+ *
+ * @param node
+ * the network node on which the flow got removed
+ * @param flow
+ * the flow that got removed. Note: It may contain only the Match
+ * and flow parameters fields. Actions may not be present.
+ */
+ public void flowRemoved(Node node, Flow flow);
+}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Represents the generic matching field
- *
+ *
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-
public class MatchField implements Cloneable, Serializable {
- private static final long serialVersionUID = 1L;
- private static final Logger logger = LoggerFactory
+ private static final long serialVersionUID = 1L;
+ private static final Logger logger = LoggerFactory
.getLogger(MatchField.class);
- private MatchType type; // the field we want to match
+ private MatchType type; // the field we want to match
private Object value; // the value of the field we want to match
- private Object mask; // the value of the mask we want to match on the specified field
+ private Object mask; // the value of the mask we want to match on the
+ // specified field
private transient boolean isValid;
// To satisfy JAXB
+ @SuppressWarnings("unused")
private MatchField() {
}
+
/**
* Mask based match constructor
- *
+ *
* @param type
* @param value
- * @param mask has to be of the same class type of value. A null mask means full match
+ * @param mask
+ * has to be of the same class type of value. A null mask means
+ * full match
*/
public MatchField(MatchType type, Object value, Object mask) {
this.type = type;
this.value = value;
this.mask = mask;
- this.isValid = checkValueType() && checkValues(); // Keep this logic, value checked only if type check is fine
+ // Keep this logic, value checked only if type check is fine
+ this.isValid = checkValueType() && checkValues();
}
/**
* Full match constructor
- *
+ *
* @param type
* @param value
*/
this.type = type;
this.value = value;
this.mask = null;
- this.isValid = checkValueType() && checkValues(); // Keep this logic, value checked only if type check is fine
+ // Keep this logic, value checked only if type check is fine
+ this.isValid = checkValueType() && checkValues();
}
/**
* Returns the value set for this match field
- *
+ *
* @return
*/
public Object getValue() {
return value;
}
-
- @XmlElement(name="value")
+
+ @XmlElement(name = "value")
private String getValueString() {
- return type.stringify(value);
+ return type.stringify(value);
}
/**
* Returns the type field this match field object is for
- *
+ *
* @return
*/
public MatchType getType() {
return type;
}
- @XmlElement(name="type")
+ @XmlElement(name = "type")
private String getTypeString() {
- return type.toString();
+ return type.toString();
}
/**
- * Returns the mask value set for this field match
- * A null mask means this is a full match
+ * Returns the mask value set for this field match A null mask means this is
+ * a full match
+ *
* @return
*/
public Object getMask() {
return mask;
}
-
- @XmlElement(name="mask")
+
+ @XmlElement(name = "mask")
private String getMaskString() {
- return type.stringify(mask);
+ return type.stringify(mask);
}
/**
* Returns the bitmask set for this field match
- *
+ *
* @return
*/
public long getBitMask() {
/**
* Returns whether the field match configuration is valid or not
- *
+ *
* @return
*/
public boolean isValid() {
}
@Override
- public int hashCode() {
- return HashCodeBuilder.reflectionHashCode(this);
+ public String toString() {
+ return type + "(" + getValueString() + "," + getMaskString() + ")";
}
@Override
- public boolean equals(Object obj) {
- return EqualsBuilder.reflectionEquals(this, obj);
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mask == null) ? 0 : mask.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
}
@Override
- public String toString() {
- return type + "(" + getValueString() + "," + getMaskString() + ")";
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MatchField other = (MatchField) obj;
+ if (type != other.type) {
+ return false;
+ }
+ return (type.equalValues(this.value, other.value) && type.equalMasks(
+ this.mask, other.mask));
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
package org.opendaylight.controller.sal.match;
import java.net.InetAddress;
+import java.util.Arrays;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NetUtils;
/**
- * Represents the binding between the id, the value and mask type and the range values
- * of the elements type that can be matched on the network frame/packet/message
- *
- *
- *
+ * Represents the binding between the id, the value and mask type and the range
+ * values of the elements type that can be matched on the network
+ * frame/packet/message
+ *
+ *
+ *
*/
public enum MatchType {
- IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0),
- DL_SRC("dlSrc", 1 << 1, Byte[].class, 0, 0xffffffffffffL),
- DL_DST("dlDst", 1 << 2, Byte[].class, 0, 0xffffffffffffL),
+ IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0),
+ DL_SRC("dlSrc", 1 << 1, Byte[].class, 0, 0xffffffffffffL),
+ DL_DST("dlDst", 1 << 2, Byte[].class, 0, 0xffffffffffffL),
DL_VLAN("dlVlan", 1 << 3, Short.class, 1, 0xfff), // 2 bytes
DL_VLAN_PR("dlVlanPriority", 1 << 4, Byte.class, 0, 0x7), // 3 bits
- DL_OUTER_VLAN("dlOuterVlan", 1 << 5, Short.class, 1, 0xfff),
- DL_OUTER_VLAN_PR("dlOuterVlanPriority", 1 << 6, Short.class, 0, 0x7),
+ DL_OUTER_VLAN("dlOuterVlan", 1 << 5, Short.class, 1, 0xfff),
+ DL_OUTER_VLAN_PR("dlOuterVlanPriority", 1 << 6, Short.class, 0, 0x7),
DL_TYPE("dlType", 1 << 7, Short.class, 0, 0xffff), // 2 bytes
NW_TOS("nwTOS", 1 << 8, Byte.class, 0, 0x3f), // 6 bits (DSCP field)
NW_PROTO("nwProto", 1 << 9, Byte.class, 0, 0xff), // 1 byte
- NW_SRC("nwSrc", 1 << 10, InetAddress.class, 0, 0),
- NW_DST("nwDst", 1 << 11, InetAddress.class, 0, 0),
+ NW_SRC("nwSrc", 1 << 10, InetAddress.class, 0, 0),
+ NW_DST("nwDst", 1 << 11, InetAddress.class, 0, 0),
TP_SRC("tpSrc", 1 << 12, Short.class, 1, 0xffff), // 2 bytes
TP_DST("tpDst", 1 << 13, Short.class, 1, 0xffff); // 2 bytes
}
/**
- * Perform the assignment type validation
+ * Perform the assignment type validation
+ *
* @param value
* @param mask
* @return
Class<?> e = this.dataType();
Class<?> g = value.getClass();
- // This is all what we need, if value type is same of match required type
+ // This is all what we need, if value type is same of match required
+ // type
if (g.equals(e)) {
return true;
}
/**
* Perform the value and mask range validation
+ *
* @param value
* @param mask
* @return
/**
* Return the mask value in 64 bits bitmask form
+ *
* @param mask
* @return
*/
public long getBitMask(Object mask) {
if (this.dataType == InetAddress.class) {
- //TODO handle Inet v4 and v6 v6 will have a second upper mask
+ // TODO handle Inet v4 and v6 v6 will have a second upper mask
return 0;
}
if (this.dataType() == Byte[].class) {
byte mac[] = (byte[]) mask;
long bitmask = 0;
for (short i = 0; i < 6; i++) {
- // bitmask |= (((long)mac[i] & 0xffL) << (long)((5-i)*8));
bitmask |= (((long) mac[i] & 0xffL) << ((5 - i) * 8));
}
return bitmask;
return 0L;
}
- public String stringify(Object value) {
- if (value == null) {
- return null;
- }
-
- switch (this) {
- case DL_DST:
- case DL_SRC:
- return HexEncode.bytesToHexStringFormat((byte[])value);
- case DL_TYPE:
- case DL_VLAN:
- return ((Integer) NetUtils.getUnsignedShort((Short)value))
- .toString();
- case NW_SRC:
- case NW_DST:
- return ((InetAddress)value).getHostAddress();
- case NW_TOS:
- return ((Integer) NetUtils.getUnsignedByte((Byte)value))
- .toString();
- case TP_SRC:
- case TP_DST:
- return ((Integer) NetUtils.getUnsignedShort((Short)value))
- .toString();
- default:
- break;
- }
- return value.toString();
- }
+ public String stringify(Object value) {
+ if (value == null) {
+ return null;
+ }
+
+ switch (this) {
+ case DL_DST:
+ case DL_SRC:
+ return HexEncode.bytesToHexStringFormat((byte[]) value);
+ case DL_TYPE:
+ case DL_VLAN:
+ return ((Integer) NetUtils.getUnsignedShort((Short) value))
+ .toString();
+ case NW_SRC:
+ case NW_DST:
+ return ((InetAddress) value).getHostAddress();
+ case NW_TOS:
+ return ((Integer) NetUtils.getUnsignedByte((Byte) value))
+ .toString();
+ case TP_SRC:
+ case TP_DST:
+ return ((Integer) NetUtils.getUnsignedShort((Short) value))
+ .toString();
+ default:
+ break;
+ }
+ return value.toString();
+ }
+
+ public boolean equalValues(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ switch (this) {
+ case DL_DST:
+ case DL_SRC:
+ return Arrays.equals((byte[]) a, (byte[]) b);
+ default:
+ return a.equals(b);
+ }
+ }
+
+ public boolean equalMasks(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ switch (this) {
+ case NW_SRC:
+ case NW_DST:
+ /*
+ * For network address mask, network node may return full mask for
+ * flows the controller generated with a null mask object
+ */
+ byte maskBytes[] = null;
+ if (a == null) {
+ maskBytes = ((InetAddress) b).getAddress();
+ } else if (b == null) {
+ maskBytes = ((InetAddress) a).getAddress();
+ }
+ if (maskBytes != null) {
+ return (NetUtils.getSubnetMaskLength(maskBytes) == 0);
+ }
+ default:
+ if (a == null) {
+ return false;
+ }
+ return a.equals(b);
+ }
+ }
}
/**
* Called when an Edge utilization is above the safety threshold
* configured on the controller
+ *
* @param edge
*/
public void edgeOverUtilized(Edge edge);
/**
* Represents the return object of the osgi service interfaces function calls.
- * It contains a code {@code StatusCode} representing the result of the call
- * and a string which describes a failure reason (if any) in human readable form.
+ * It contains a code {@code StatusCode} representing the result of the call and
+ * a string which describes a failure reason (if any) in human readable form.
*/
public class Status {
- StatusCode code;
- String description;
-
- /**
- * Generates an instance of the Status class.
- *
- * @param errorCode The status code. If passed as null, code will be
- * stored as {@code StatusCode.UNDEFINED}
- * @param description The human readable description of the status. If passed
- * as null, description will be inferred by the code
- */
- public Status(StatusCode errorCode, String description) {
- this.code = (errorCode != null)? errorCode : StatusCode.UNDEFINED;
- this.description = (description != null)? description : this.code.toString();
- }
-
- /**
- * Returns the status code
- * @return the {@code StatusCode} representing the status code
- */
- public StatusCode getCode() {
- return code;
- }
-
- /**
- * Returns a human readable description of the failure if any
- * @return a string representing the reason of failure
- */
- public String getDescription() {
- return description;
- }
-
- /**
- * Tells whether the status is successful
- * @return true if the Status code is {@code StatusCode.SUCCESS}
- */
- public boolean isSuccess() {
- return code == StatusCode.SUCCESS;
- }
-
- @Override
- public String toString() {
- return code + ": " + description;
- }
+ StatusCode code;
+ String description;
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((code == null) ? 0 : code.hashCode());
- return result;
- }
+ /**
+ * Generates an instance of the Status class. This is used as return code
+ * for internal API2 function calls. This constructor allows to specify,
+ * beside the Status Code, a custom human readable description to add more
+ * information about the status.
+ *
+ * @param errorCode
+ * The status code. If passed as null, code will be stored as
+ * {@code StatusCode.UNDEFINED}
+ * @param description
+ * The human readable description of the status. If passed as
+ * null, description will be inferred by the code
+ */
+ public Status(StatusCode errorCode, String description) {
+ this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
+ this.description = (description != null) ? description : this.code
+ .toString();
+ }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- Status other = (Status) obj;
- if (code != other.code)
- return false;
- return true;
- }
+ /**
+ * Generates an instance of the Status class based on the passed StatusCode
+ * only. The description field of the Status object will be inferred by the
+ * status code.
+ *
+ * @param errorCode
+ * The status code. If passed as null, code will be stored as
+ * {@code StatusCode.UNDEFINED}
+ */
+ public Status(StatusCode errorCode) {
+ this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
+ this.description = (description != null) ? description : this.code
+ .toString();
+ }
+
+ /**
+ * Returns the status code
+ *
+ * @return the {@code StatusCode} representing the status code
+ */
+ public StatusCode getCode() {
+ return code;
+ }
+
+ /**
+ * Returns a human readable description of the failure if any
+ *
+ * @return a string representing the reason of failure
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Tells whether the status is successful
+ *
+ * @return true if the Status code is {@code StatusCode.SUCCESS}
+ */
+ public boolean isSuccess() {
+ return code == StatusCode.SUCCESS;
+ }
+
+ @Override
+ public String toString() {
+ return code + ": " + description;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((code == null) ? 0 : code.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;
+ Status other = (Status) obj;
+ if (code != other.code)
+ return false;
+ return true;
+ }
}
}
}
+ @Test
+ public void testEqualityNetMask() throws Exception {
+
+ InetAddress srcIP = InetAddress.getByName("1.1.1.1");
+ InetAddress ipMask = InetAddress.getByName("255.255.255.255");
+ InetAddress srcIP2 = InetAddress.getByName("1.1.1.1");
+ InetAddress ipMask2 = null;
+ short ethertype = EtherTypes.IPv4.shortValue();
+ short ethertype2 = EtherTypes.IPv4.shortValue();
+
+ /*
+ * Create a SAL Flow aFlow
+ */
+ Match match1 = new Match();
+ Match match2 = new Match();
+
+ match1.setField(MatchType.DL_TYPE, ethertype);
+ match1.setField(MatchType.NW_SRC, srcIP, ipMask);
+
+ match2.setField(MatchType.DL_TYPE, ethertype2);
+ match2.setField(MatchType.NW_SRC, srcIP2, ipMask2);
+
+ Assert.assertTrue(match1.equals(match2));
+
+ ipMask2 = InetAddress.getByName("255.255.255.255");
+ match2.setField(MatchType.NW_SRC, srcIP2, ipMask2);
+
+ srcIP = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355");
+ srcIP2 = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355");
+ ipMask = null;
+ ipMask2 = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ ethertype = EtherTypes.IPv6.shortValue();
+ ethertype2 = EtherTypes.IPv6.shortValue();
+
+ match1.setField(MatchType.DL_TYPE, ethertype);
+ match1.setField(MatchType.NW_SRC, srcIP, ipMask);
+
+ match2.setField(MatchType.DL_TYPE, ethertype2);
+ match2.setField(MatchType.NW_SRC, srcIP2, ipMask2);
+
+ Assert.assertTrue(match1.equals(match2));
+ }
+
@Test
public void testCloning() throws Exception {
Node node = NodeCreator.createOFNode(7l);
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
package org.opendaylight.controller.sal.implementation.internal;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
import org.opendaylight.controller.sal.inventory.IInventoryService;
import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
import org.opendaylight.controller.sal.inventory.IPluginInInventoryService;
.getLogger(Activator.class);
/**
- * Function called when the activator starts just after some
- * initializations are done by the
- * ComponentActivatorAbstractBase.
- *
+ * Function called when the activator starts just after some initializations
+ * are done by the ComponentActivatorAbstractBase.
+ *
*/
public void init() {
}
/**
- * Function called when the activator stops just before the
- * cleanup done by ComponentActivatorAbstractBase
- *
+ * Function called when the activator stops just before the cleanup done by
+ * ComponentActivatorAbstractBase
+ *
*/
public void destroy() {
}
/**
- * Function that is used to communicate to dependency manager the
- * list of known implementations for services inside a container
- *
- *
+ * Function that is used to communicate to dependency manager the list of
+ * known implementations for services inside a container
+ *
+ *
* @return An array containing all the CLASS objects that will be
- * instantiated in order to get an fully working implementation
- * Object
+ * instantiated in order to get an fully working implementation
+ * Object
*/
public Object[] getImplementations() {
Object[] res = { Topology.class, Inventory.class,
}
/**
- * Function that is called when configuration of the dependencies
- * is required.
- *
- * @param c dependency manager Component object, used for
- * configuring the dependencies exported and imported
- * @param imp Implementation class that is being configured,
- * needed as long as the same routine can configure multiple
- * implementations
- * @param containerName The containerName being configured, this allow
- * also optional per-container different behavior if needed, usually
- * should not be the case though.
+ * Function that is called when configuration of the dependencies is
+ * required.
+ *
+ * @param c
+ * dependency manager Component object, used for configuring the
+ * dependencies exported and imported
+ * @param imp
+ * Implementation class that is being configured, needed as long
+ * as the same routine can configure multiple implementations
+ * @param containerName
+ * The containerName being configured, this allow also optional
+ * per-container different behavior if needed, usually should not
+ * be the case though.
*/
public void configureInstance(Component c, Object imp, String containerName) {
if (imp.equals(Topology.class)) {
// export the service for Apps and Plugins
- c.setInterface(new String[] {
- IPluginOutTopologyService.class.getName(),
- ITopologyService.class.getName() }, null);
+ c.setInterface(
+ new String[] { IPluginOutTopologyService.class.getName(),
+ ITopologyService.class.getName() }, null);
// There can be multiple Topology listeners or there could
// be none, hence the dependency is optional
- c.add(createContainerServiceDependency(containerName).setService(
- IListenTopoUpdates.class).setCallbacks("setUpdateService",
- "unsetUpdateService").setRequired(false));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IListenTopoUpdates.class)
+ .setCallbacks("setUpdateService", "unsetUpdateService")
+ .setRequired(false));
// There can be multiple southbound plugins or there could
// be none, the dependency is optional
- c.add(createContainerServiceDependency(containerName).setService(
- IPluginInTopologyService.class).setCallbacks(
- "setPluginService", "unsetPluginService")
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginInTopologyService.class)
+ .setCallbacks("setPluginService", "unsetPluginService")
.setRequired(false));
}
if (imp.equals(Inventory.class)) {
// export the service
- c.setInterface(new String[] {
- IPluginOutInventoryService.class.getName(),
- IInventoryService.class.getName() }, null);
+ c.setInterface(
+ new String[] { IPluginOutInventoryService.class.getName(),
+ IInventoryService.class.getName() }, null);
// Now lets add a service dependency to make sure the
// provider of service exists
- c.add(createContainerServiceDependency(containerName).setService(
- IListenInventoryUpdates.class).setCallbacks(
- "setUpdateService", "unsetUpdateService")
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IListenInventoryUpdates.class)
+ .setCallbacks("setUpdateService", "unsetUpdateService")
.setRequired(false));
- c
- .add(createContainerServiceDependency(containerName)
- .setService(IPluginInInventoryService.class)
- .setCallbacks("setPluginService",
- "unsetPluginService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginInInventoryService.class)
+ .setCallbacks("setPluginService", "unsetPluginService")
+ .setRequired(true));
}
if (imp.equals(FlowProgrammerService.class)) {
- // It is the provider of IFlowProgrammerService
- c.setInterface(IFlowProgrammerService.class.getName(), null);
- //It is also the consumer of IPluginInFlowProgrammerService
- c.add(createServiceDependency().setService(
- IPluginInFlowProgrammerService.class).setCallbacks(
- "setService", "unsetService").setRequired(true));
+ c.setInterface(
+ new String[] { IFlowProgrammerService.class.getName(),
+ IPluginOutFlowProgrammerService.class.getName() },
+ null);
+
+ c.add(createServiceDependency()
+ .setService(IPluginInFlowProgrammerService.class)
+ .setCallbacks("setService", "unsetService")
+ .setRequired(false));
+ c.add(createServiceDependency()
+ .setService(IFlowProgrammerListener.class)
+ .setCallbacks("setListener", "unsetListener")
+ .setRequired(false));
}
if (imp.equals(ReadService.class)) {
// It is the provider of IReadService
c.setInterface(IReadService.class.getName(), null);
- //It is also the consumer of IPluginInReadService
- c.add(createContainerServiceDependency(containerName).setService(
- IPluginInReadService.class).setCallbacks("setService",
- "unsetService").setRequired(true));
+ // It is also the consumer of IPluginInReadService
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginInReadService.class)
+ .setCallbacks("setService", "unsetService")
+ .setRequired(true));
}
/************************/
/* DATA PACKET SERVICES */
/************************/
if (imp.equals(DataPacketService.class)) {
- c.setInterface(new String[] {
- IPluginOutDataPacketService.class.getName(),
- IDataPacketService.class.getName() }, null);
+ c.setInterface(
+ new String[] { IPluginOutDataPacketService.class.getName(),
+ IDataPacketService.class.getName() }, null);
// Optionally use PluginInDataService if any southbound
// protocol plugin exists
- c.add(createContainerServiceDependency(containerName).setService(
- IPluginInDataPacketService.class).setCallbacks(
- "setPluginInDataService", "unsetPluginInDataService")
- .setRequired(false));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IPluginInDataPacketService.class)
+ .setCallbacks("setPluginInDataService",
+ "unsetPluginInDataService").setRequired(false));
// Optionally listed to IListenDataPacket services
- c.add(createContainerServiceDependency(containerName).setService(
- IListenDataPacket.class).setCallbacks(
- "setListenDataPacket", "unsetListenDataPacket")
- .setRequired(false));
+ c.add(createContainerServiceDependency(containerName)
+ .setService(IListenDataPacket.class)
+ .setCallbacks("setListenDataPacket",
+ "unsetListenDataPacket").setRequired(false));
}
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Node.NodeIDType;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
+import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.slf4j.LoggerFactory;
/**
- * The SAL Flow Programmer Service. It dispatches the flow programming
- * requests to the proper SDN protocol plugin
- *
- *
- *
+ * The SAL Flow Programmer Service. It dispatches the flow programming requests
+ * to the proper SDN protocol plugin and it notifies about asynchronous messages
+ * received from the network node related to flow programming.
*/
public class FlowProgrammerService implements IFlowProgrammerService,
- CommandProvider {
+ IPluginOutFlowProgrammerService, CommandProvider {
protected static final Logger logger = LoggerFactory
.getLogger(FlowProgrammerService.class);
- private ConcurrentHashMap<String, IPluginInFlowProgrammerService>
- pluginFlowProgrammer =
- new ConcurrentHashMap<String, IPluginInFlowProgrammerService>();
+ private ConcurrentHashMap<String, IPluginInFlowProgrammerService> pluginFlowProgrammer;
+ private Set<IFlowProgrammerListener> listener;
+
+ public FlowProgrammerService() {
+ pluginFlowProgrammer = new ConcurrentHashMap<String, IPluginInFlowProgrammerService>();
+ listener = new HashSet<IFlowProgrammerListener>();
+ }
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
void init() {
logger.debug("INIT called!");
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
- *
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
*/
void destroy() {
// Clear previous registration to avoid they are left hanging
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
- *
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
*/
void start() {
logger.debug("START called!");
}
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
- *
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
*/
void stop() {
logger.debug("STOP called!");
String type = null;
for (Object e : props.entrySet()) {
Map.Entry entry = (Map.Entry) e;
- logger.trace("Prop key:({}) value:({})",entry.getKey(),
- entry.getValue());
+ logger.trace("Prop key:({}) value:({})", entry.getKey(),
+ entry.getValue());
}
Object value = props.get("protocolPluginType");
+ "protocolPluginType provided");
} else {
this.pluginFlowProgrammer.put(type, s);
- logger.debug("Stored the pluginFlowProgrammer for type: {}",type);
+ logger.debug("Stored the pluginFlowProgrammer for type: {}", type);
}
}
- public void unsetService(Map props,
- IPluginInFlowProgrammerService s) {
+ public void unsetService(Map props, IPluginInFlowProgrammerService s) {
if (this.pluginFlowProgrammer == null) {
logger.error("pluginFlowProgrammer store null");
return;
logger.debug("Received unsetpluginFlowProgrammer request");
for (Object e : props.entrySet()) {
Map.Entry entry = (Map.Entry) e;
- logger.trace("Prop key:({}) value:({})",entry.getKey(),
- entry.getValue());
+ logger.trace("Prop key:({}) value:({})", entry.getKey(),
+ entry.getValue());
}
Object value = props.get("protocoloPluginType");
}
}
+ public void setListener(IFlowProgrammerListener s) {
+ this.listener.add(s);
+ }
+
+ public void unsetListener(IFlowProgrammerListener s) {
+ this.listener.remove(s);
+ }
+
@Override
public Status addFlow(Node node, Flow flow) {
if (pluginFlowProgrammer != null) {
if (this.pluginFlowProgrammer.get(node.getType()) != null) {
- return this.pluginFlowProgrammer.get(node.getType())
- .addFlow(node, flow);
+ return this.pluginFlowProgrammer.get(node.getType()).addFlow(
+ node, flow);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
if (pluginFlowProgrammer != null) {
if (this.pluginFlowProgrammer.get(node.getType()) != null) {
return this.pluginFlowProgrammer.get(node.getType())
- .removeFlow(node, flow);
+ .removeFlow(node, flow);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
if (pluginFlowProgrammer != null) {
if (this.pluginFlowProgrammer.get(node.getType()) != null) {
return this.pluginFlowProgrammer.get(node.getType())
- .removeAllFlows(node);
+ .removeAllFlows(node);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
if (pluginFlowProgrammer != null) {
if (this.pluginFlowProgrammer.get(node.getType()) != null) {
return this.pluginFlowProgrammer.get(node.getType())
- .modifyFlow(node, oldFlow, newFlow);
+ .modifyFlow(node, oldFlow, newFlow);
}
}
return new Status(StatusCode.NOSERVICE, "Plugin unuvailable");
}
+ @Override
+ public void flowRemoved(Node node, Flow flow) {
+ for (IFlowProgrammerListener l : listener) {
+ l.flowRemoved(node, flow);
+ }
+ }
+
// ---------------- OSGI TEST CODE ------------------------------//
private void registerWithOSGIConsole() {
public String getHelp() {
StringBuffer help = new StringBuffer();
help.append("---SAL Flow Programmer testing commands---\n");
- help
- .append("\t addflow <sid> - Add a sample flow to the openflow switch <sid>\n");
- help
- .append("\t removeflow <sid> - Remove the sample flow from the openflow switch <sid>\n");
+ help.append("\t addflow <sid> - Add a sample flow to the openflow switch <sid>\n");
+ help.append("\t removeflow <sid> - Remove the sample flow from the openflow switch <sid>\n");
return help.toString();
}
Flow flowA = getSampleFlow(node);
Flow flowB = getSampleFlow(node);
Match matchB = flowB.getMatch();
- matchB.setField(MatchType.NW_DST, InetAddress
- .getByName("190.190.190.190"));
+ matchB.setField(MatchType.NW_DST,
+ InetAddress.getByName("190.190.190.190"));
flowB.setMatch(matchB);
ci.println(this.modifyFlow(node, flowA, flowB));
}
.getByName("2001:420:281:1004:407a:57f4:4d15:c355");
InetAddress dstIP = InetAddress
.getByName("2001:420:281:1004:e123:e688:d655:a1b0");
- InetAddress ipMask = null; //InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); V6Match implementation assumes no mask is specified
- InetAddress ipMask2 = null; //InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0");
+ InetAddress ipMask = null; // InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0");
+ // V6Match implementation assumes no mask is
+ // specified
+ InetAddress ipMask2 = null; // InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0");
short ethertype = EtherTypes.IPv6.shortValue();
short vlan = (short) 27;
byte vlanPr = (byte) 3;
Byte tos = 4;
byte proto = IPProtocols.UDP.byteValue();
short src = (short) 5500;
- //short dst = 80;
+ // short dst = 80;
/*
* Create a SAL Flow aFlow
match.setField(MatchType.DL_DST, dstMac);
match.setField(MatchType.DL_TYPE, ethertype);
match.setField(MatchType.DL_VLAN, vlan);
- match.setField(MatchType.DL_VLAN_PR, vlanPr); //V6Match does not handle this properly...
+ match.setField(MatchType.DL_VLAN_PR, vlanPr); // V6Match does not handle
+ // this properly...
match.setField(MatchType.NW_SRC, srcIP, ipMask);
match.setField(MatchType.NW_DST, dstIP, ipMask2);
match.setField(MatchType.NW_TOS, tos);
match.setField(MatchType.NW_PROTO, proto);
- match.setField(MatchType.TP_SRC, src); //V6Match does not handle this properly...
- //match.setField(MatchType.TP_DST, dst); V6Match does not handle this properly...
+ match.setField(MatchType.TP_SRC, src); // V6Match does not handle this
+ // properly...
+ // match.setField(MatchType.TP_DST, dst); V6Match does not handle this
+ // properly...
List<Action> actions = new ArrayList<Action>();
actions.add(new Output(oport));
return flow;
}
+
}