ICacheUpdateAware<Object,Object>,
CommandProvider,
IFlowProgrammerListener {
- private static final String NODEDOWN = "Node is Down";
- private static final String SUCCESS = StatusCode.SUCCESS.toString();
+
private static final Logger log = LoggerFactory.getLogger(ForwardingRulesManager.class);
- private static final String PORTREMOVED = "Port removed";
private static final Logger logsync = LoggerFactory.getLogger("FRMsync");
+ private static final String PORTREMOVED = "Port removed";
+ private static final String NODEDOWN = "Node is Down";
+ private static final String INVALID_FLOW_ENTRY = "Invalid FlowEntry";
private String frmFileName;
private String portGroupFileName;
private ConcurrentMap<Integer, FlowConfig> staticFlows;
* necessity non-transactional as long as need to be able to synchronize
* states also while a transaction is in progress
*/
- static final String WORKORDERCACHE = "frm.workOrder";
- static final String WORKSTATUSCACHE = "frm.workStatus";
+ static final String WORK_ORDER_CACHE = "frm.workOrder";
+ static final String WORK_STATUS_CACHE = "frm.workStatus";
/*
* Data structure responsible for distributing the FlowEntryInstall requests
private Status addEntry(FlowEntry flowEntry, boolean async) {
// Sanity Check
- if (flowEntry == null || flowEntry.getNode() == null) {
- String msg = "Invalid FlowEntry";
- String logMsg = msg + ": {}";
+ if (flowEntry == null || flowEntry.getNode() == null || flowEntry.getFlow() == null) {
+ String logMsg = INVALID_FLOW_ENTRY + ": {}";
log.warn(logMsg, flowEntry);
- return new Status(StatusCode.NOTACCEPTABLE, msg);
+ return new Status(StatusCode.NOTACCEPTABLE, INVALID_FLOW_ENTRY);
+ }
+
+ /*
+ * Redundant Check: Check if the request is a redundant one from the
+ * same application the flowEntry is equal to an existing one. Given we
+ * do not have an application signature in the requested FlowEntry yet,
+ * we are here detecting the above condition by comparing the flow
+ * names, if set. If they are equal to the installed flow, most likely
+ * this is a redundant installation request from the same application
+ * and we can silently return success
+ *
+ * TODO: in future a sort of application reference list mechanism will
+ * be added to the FlowEntry so that exact flow can be used by different
+ * applications.
+ */
+ FlowEntry present = this.originalSwView.get(flowEntry);
+ if (present != null) {
+ boolean sameFlow = present.getFlow().equals(flowEntry.getFlow());
+ boolean sameApp = present.getFlowName() != null && present.getFlowName().equals(flowEntry.getFlowName());
+ if (sameFlow && sameApp) {
+ log.trace("Skipping redundant request for flow {} on node {}", flowEntry.getFlowName(),
+ flowEntry.getNode());
+ return new Status(StatusCode.SUCCESS, "Entry is already present");
+ }
}
/*
succeded = ret;
} else {
error = ret;
- log.warn("Failed to install the entry: {}. The failure is: {}", installEntry, ret.getDescription());
+ log.trace("Failed to install the entry: {}. The failure is: {}", installEntry, ret.getDescription());
}
}
// Sanity checks
if (currentFlowEntry == null || currentFlowEntry.getNode() == null || newFlowEntry == null
- || newFlowEntry.getNode() == null) {
- String msg = "Modify: Invalid FlowEntry";
+ || newFlowEntry.getNode() == null || newFlowEntry.getFlow() == null) {
+ String msg = "Modify: " + INVALID_FLOW_ENTRY;
String logMsg = msg + ": {} or {}";
log.warn(logMsg, currentFlowEntry, newFlowEntry);
return new Status(StatusCode.NOTACCEPTABLE, msg);
.getFlow());
if (!status.isSuccess()) {
- log.warn("SDN Plugin failed to program the flow: {}. The failure is: {}", newEntries.getInstall(),
+ log.trace("SDN Plugin failed to program the flow: {}. The failure is: {}", newEntries.getInstall(),
status.getDescription());
return status;
}
Status error = new Status(null, null);
// Sanity Check
- if (flowEntry == null || flowEntry.getNode() == null) {
- String msg = "Invalid FlowEntry";
- String logMsg = msg + ": {}";
+ if (flowEntry == null || flowEntry.getNode() == null || flowEntry.getFlow() == null) {
+ String logMsg = INVALID_FLOW_ENTRY + ": {}";
log.warn(logMsg, flowEntry);
- return new Status(StatusCode.NOTACCEPTABLE, msg);
+ return new Status(StatusCode.NOTACCEPTABLE, INVALID_FLOW_ENTRY);
}
// Derive the container flows merged installed entries
if (!ret.isSuccess()) {
error = ret;
- log.warn("Failed to remove the entry: {}. The failure is: {}", entry.getInstall(), ret.getDescription());
+ log.trace("Failed to remove the entry: {}. The failure is: {}", entry.getInstall(), ret.getDescription());
if (installedList.size() == 1) {
// If we had only one entry to remove, this is fatal failure
return error;
.getFlow());
if (!status.isSuccess()) {
- log.warn("SDN Plugin failed to program the flow: {}. The failure is: {}", entry.getInstall(),
+ log.trace("SDN Plugin failed to remove the flow: {}. The failure is: {}", entry.getInstall(),
status.getDescription());
return status;
}
.getFlow());
if (!status.isSuccess()) {
- log.warn("SDN Plugin failed to program the flow: {}. The failure is: {}", entry.getInstall(),
+ log.trace("SDN Plugin failed to program the flow: {}. The failure is: {}", entry.getInstall(),
status.getDescription());
return status;
}
updateLocalDatabase(target, false);
} else {
// log the error
- log.warn("SDN Plugin failed to remove the flow: {}. The failure is: {}", target.getInstall(),
+ log.trace("SDN Plugin failed to remove the flow: {}. The failure is: {}", target.getInstall(),
status.getDescription());
}
clusterContainerService.createCache("frm.TSPolicies",
EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
- clusterContainerService.createCache(WORKSTATUSCACHE,
+ clusterContainerService.createCache(WORK_STATUS_CACHE,
EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
- clusterContainerService.createCache(WORKORDERCACHE,
+ clusterContainerService.createCache(WORK_ORDER_CACHE,
EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
} catch (CacheConfigException cce) {
log.error("Retrieval of frm.TSPolicies cache failed for Container {}", container.getName());
}
- map = clusterContainerService.getCache(WORKORDERCACHE);
+ map = clusterContainerService.getCache(WORK_ORDER_CACHE);
if (map != null) {
workOrder = (ConcurrentMap<FlowEntryDistributionOrder, FlowEntryInstall>) map;
} else {
- log.error("Retrieval of " + WORKORDERCACHE + " cache failed for Container {}", container.getName());
+ log.error("Retrieval of " + WORK_ORDER_CACHE + " cache failed for Container {}", container.getName());
}
- map = clusterContainerService.getCache(WORKSTATUSCACHE);
+ map = clusterContainerService.getCache(WORK_STATUS_CACHE);
if (map != null) {
workStatus = (ConcurrentMap<FlowEntryDistributionOrder, Status>) map;
} else {
- log.error("Retrieval of " + WORKSTATUSCACHE + " cache failed for Container {}", container.getName());
+ log.error("Retrieval of " + WORK_STATUS_CACHE + " cache failed for Container {}", container.getName());
}
}
boolean multipleFlowPush = false;
String error;
Status status;
- config.setStatus(SUCCESS);
+ config.setStatus(StatusCode.SUCCESS.toString());
// Presence check
if (flowConfigExists(config)) {
continue;
}
if (config.getNode().equals(node)) {
- if (config.installInHw() && !config.getStatus().equals(SUCCESS)) {
+ if (config.installInHw() && !config.getStatus().equals(StatusCode.SUCCESS.toString())) {
Status status = this.installFlowEntryAsync(config.getFlowEntry());
config.setStatus(status.getDescription());
}
config.setStatus("Removed from node because in container mode");
break;
case REMOVED:
- config.setStatus(SUCCESS);
+ config.setStatus(StatusCode.SUCCESS.toString());
break;
default:
}
.installFlowEntry(target.getFlowEntry());
if (status.isSuccess()) {
// Update Configuration database
- target.setStatus(SUCCESS);
+ target.setStatus(StatusCode.SUCCESS.toString());
target.toggleInstallation();
staticFlows.put(key, target);
}
if (n != null && connectionManager.getLocalityStatus(n) == ConnectionLocality.LOCAL) {
Status status = this.removeEntryInternal(flowEntryHw, false);
if (!status.isSuccess()) {
- log.warn("Failed to remove entry: {}. The failure is: {}", flowEntryHw, status.getDescription());
+ log.trace("Failed to remove entry: {}. The failure is: {}", flowEntryHw, status.getDescription());
}
} else {
log.debug("Not removing entry {} because not connected locally, the remote guy will do it's job",
List<FlowConfig> flowConfigForNode = getStaticFlows(nodeConnector.getNode());
for (FlowConfig flowConfig : flowConfigForNode) {
if (doesFlowContainNodeConnector(flowConfig.getFlow(), nodeConnector)) {
- if (flowConfig.installInHw() && !flowConfig.getStatus().equals(SUCCESS)) {
+ if (flowConfig.installInHw() && !flowConfig.getStatus().equals(StatusCode.SUCCESS.toString())) {
Status status = this.installFlowEntry(flowConfig.getFlowEntry());
if (!status.isSuccess()) {
flowConfig.setStatus(status.getDescription());
} else {
- flowConfig.setStatus(SUCCESS);
+ flowConfig.setStatus(StatusCode.SUCCESS.toString());
}
updated = true;
}
if (target != null) {
// Update Configuration database
target.toggleInstallation();
- target.setStatus(SUCCESS);
+ target.setStatus(StatusCode.SUCCESS.toString());
staticFlows.put(key, target);
}
*/
return;
}
- if (cacheName.equals(WORKORDERCACHE)) {
+ if (cacheName.equals(WORK_ORDER_CACHE)) {
logsync.trace("Got a WorkOrderCacheUpdate for {}", key);
/*
* This is the case of one workOrder becoming available, so we need
// processing
pendingEvents.offer(new WorkOrderEvent(fe, (FlowEntryInstall) new_value));
}
- } else if (cacheName.equals(WORKSTATUSCACHE)) {
+ } else if (cacheName.equals(WORK_STATUS_CACHE)) {
logsync.trace("Got a WorkStatusCacheUpdate for {}", key);
/*
* This is the case of one workOrder being completed and a status