logger.info("Starting the ClusterManager");
try {
//FIXME keeps throwing FileNotFoundException
- this.cm = new DefaultCacheManager("/config/infinispan-config.xml");
+ this.cm = new DefaultCacheManager("config/infinispan-config.xml");
logger.debug("Allocated ClusterManager");
if (this.cm != null) {
this.cm.start();
<global>
<transport>
<properties>
- <property name="configurationFile" value="/config/jgroups.xml"/>
+ <property name="configurationFile" value="config/jgroups.xml"/>
</properties>
</transport>
<!-- Enable JMX statistics -->
--- /dev/null
+package org.opendaylight.controller.clustering.services_implementation.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.infinispan.CacheImpl;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.clustering.services.IClusterServices.cacheMode;
+
+public class ClusterManagerTest {
+
+ @Test
+ public void NoManagerSetTest() throws CacheExistException,
+ CacheConfigException {
+ ClusterManager cm = new ClusterManager();
+ CacheImpl<String, Integer> c1 = null;
+ CacheImpl<String, Integer> c2 = null;
+ Assert.assertNull(cm.createCache("Container", "Cache", null));
+ Assert.assertNull(cm.getCacheProperties("Container", "Cache"));
+ Assert.assertNull(cm.getCache("Container", "Cache"));
+ Assert.assertFalse(cm.existCache("Container", "Cache"));
+ Assert.assertNull(cm.getCacheList("Container"));
+ Assert.assertTrue(cm.amIStandby());
+ Assert.assertNull(cm.getActiveAddress());
+ Assert.assertNull(cm.getMyAddress());
+ Assert.assertNull(cm.getClusteredControllers());
+ }
+
+ @Test
+ public void WithManagerTest() throws CacheExistException,
+ CacheConfigException {
+
+ ClusterManager cm = new ClusterManager();
+ CacheImpl<String, Integer> c1 = null;
+ CacheImpl<String, Integer> c2 = null;
+
+ cm.start();
+
+ // Check no cache created yet
+ assertFalse(cm.existCache("NonExistantContainerName",
+ "NonExistantCacheName"));
+
+ // Create cache with no cacheMode set, expecting it to fail
+ HashSet<cacheMode> cacheModeSet = new HashSet<cacheMode>();
+ Assert.assertNull(cm.createCache("Container1", "Cache1", cacheModeSet));
+
+ // Create first cache as transactional
+ cacheModeSet.add(cacheMode.TRANSACTIONAL);
+ try {
+ c1 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache1", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(false);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(false);
+ }
+
+ // Try creating exact same cache again
+ try {
+ c1 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache1", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(true);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(false);
+ }
+
+ // Create second cache with both types of cacheMode, expecting it to
+ // complain
+ cacheModeSet.add(cacheMode.NON_TRANSACTIONAL);
+ try {
+ c2 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache2", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(false);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(true);
+ }
+
+ // Create second cache properly this time, as non_transactional
+ cacheModeSet.remove(cacheMode.TRANSACTIONAL);
+ try {
+ c2 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache2", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(false);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(false);
+ }
+
+ // Make sure correct caches exists
+ Assert.assertTrue(cm.existCache("Container1", "Cache1"));
+ c1 = (CacheImpl<String, Integer>) cm.getCache("Container1", "Cache1");
+ Assert.assertTrue(c1 != null);
+
+ Assert.assertTrue(cm.existCache("Container1", "Cache2"));
+ c2 = (CacheImpl<String, Integer>) cm.getCache("Container1", "Cache2");
+ Assert.assertTrue(c2 != null);
+
+ Assert.assertNull(cm.getCache("Container1", "Cache3"));
+
+ // Get CacheList
+ HashSet<String> cacheList = (HashSet<String>) cm
+ .getCacheList("Container2");
+ Assert.assertEquals(0, cacheList.size());
+
+ cacheList = (HashSet<String>) cm.getCacheList("Container1");
+ Assert.assertEquals(2, cacheList.size());
+ Assert.assertTrue(cacheList.contains("Cache1"));
+ Assert.assertTrue(cacheList.contains("Cache2"));
+
+ // Get CacheProperties
+ Assert.assertNull(cm.getCacheProperties("Container1", ""));
+ Properties p = cm.getCacheProperties("Container1", "Cache1");
+ Assert.assertEquals(3, p.size());
+ Assert.assertNotNull(p
+ .getProperty(IClusterServices.cacheProps.TRANSACTION_PROP
+ .toString()));
+ Assert.assertNotNull(p
+ .getProperty(IClusterServices.cacheProps.CLUSTERING_PROP
+ .toString()));
+ Assert.assertNotNull(p
+ .getProperty(IClusterServices.cacheProps.LOCKING_PROP
+ .toString()));
+
+ // Destroy cache1 and make sure it's gone
+ cm.destroyCache("Container1", "Cache1");
+ cm.destroyCache("Container1", "Cache3");
+ Assert.assertFalse(cm.existCache("Container1", "Cache1"));
+ Assert.assertTrue(cm.existCache("Container1", "Cache2"));
+
+ // Check amIStandBy()
+ boolean standby = cm.amIStandby();
+ Assert.assertFalse(standby);
+
+ // Check addresses, which are all loopback
+ InetAddress activeAddress = cm.getActiveAddress();
+ Assert.assertEquals("/127.0.0.1", activeAddress.toString());
+ InetAddress myAddress = cm.getMyAddress();
+ Assert.assertEquals("/127.0.0.1", myAddress.toString());
+
+ List<InetAddress> cc = cm.getClusteredControllers();
+ Assert.assertEquals(0, cc.size());
+
+ cm.stop();
+ }
+
+}
private FlowEntry original;
private ContainerFlow cFlow;
private FlowEntry install;
+ transient private long requestId; // async request id
transient private boolean deletePending;
public FlowEntryInstall(FlowEntry original, ContainerFlow cFlow) {
this.install = (cFlow == null) ? original.clone() : original
.mergeWith(cFlow);
deletePending = false;
+ requestId = 0;
}
@Override
this.deletePending = true;
}
+ public void setRequestId(long rid) {
+ this.requestId = rid;
+ }
+
+ public long getRequestId() {
+ return requestId;
+ }
+
@Override
public String toString() {
- return "[Install = " + install + " Original: " + original + " cFlow: "
- + cFlow + "]";
+ return "[Install = " + install + " Original = " + original + " cFlow = "
+ + cFlow + " rid = " + requestId + "]";
}
}
* not valid an error code is returned. If the existing flow is equal to the
* passed one it will be a no op and success code is returned.
*
+ *
* @param newone
* the new flow entry to install
* @return the {@code Status} object indicating the result of this action
*/
public Status modifyOrAddFlowEntry(FlowEntry newone);
+ /**
+ * It requests FRM to install the passed Flow Entry through an asynchronous
+ * call. A unique request id is returned to the caller. FRM will request the
+ * SDN protocol plugin to install the flow on the network node. As immediate
+ * result of this asynchronous call, FRM will update its flow database as if
+ * the flow was successfully installed.
+ *
+ * @param flow
+ * the flow entry to install
+ * @return the status of this request containing the request id associated
+ * to this asynchronous request
+ */
+ public Status installFlowEntryAsync(FlowEntry flow);
+
+ /**
+ * It requests FRM to remove the passed Flow Entry through an asynchronous
+ * call. A unique request id is returned to the caller. FRM will request the
+ * SDN protocol plugin to uninstall the flow from the network node. As
+ * immediate result of this asynchronous call, FRM will update its flow
+ * database as if the flow was successfully installed.
+ *
+ * @param flow
+ * the flow entry to uninstall
+ * @return the status of this request containing the unique id associated to
+ * this asynchronous request
+ */
+ public Status uninstallFlowEntryAsync(FlowEntry flow);
+
+ /**
+ * It requests FRM to replace the currently installed Flow Entry with the
+ * new one through an asynchronous call. A unique request id is returned to
+ * the caller. It is up to the SDN protocol plugin to decide how to convey
+ * this message to the network node. It could be a delete + add or a single
+ * modify message depending on the SDN protocol specifications. If the
+ * current flow is equal to the new one it will be a no op.
+ *
+ * @param current
+ * the current flow entry to modify
+ * @param newone
+ * the new flow entry which will replace the current one
+ * @return the status of this request containing the request id associated
+ * to this asynchronous request
+ */
+ public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone);
+
+ /**
+ * It requests the FRM to replace the currently installed Flow Entry with
+ * the new one through an asynchronous call. A unique request id is returned
+ * to the caller. The currently installed entry is derived by the Match
+ * portion of the passed Flow. FRM looks in its database for a previously
+ * installed FlowEntry which Match equals the Match of the passed Flow. If
+ * it finds it, it will request the SDN protocol plugin to replace the
+ * existing flow with the new one on the network node. If it does not find
+ * it, it will request plugin to add the new flow. If the passed entry is
+ * not valid a zero request id is returned. If the existing flow is equal to
+ * the passed one it will be a no op.
+ *
+ * @param newone
+ * the new flow entry to install
+ * @return the unique id associated to this request. In case of not
+ * acceptable request -1 will be returned.
+ */
+ public Status modifyOrAddFlowEntryAsync(FlowEntry newone);
+
+ /**
+ * Requests ForwardingRulesManager to solicit the network node to inform
+ * us about the status of his execution on the asynchronous requests that
+ * were sent to it so far. It is a way for an application to poke the
+ * network node in order to get a feedback asap on the asynchronous
+ * requests generated by the application. It is a non-blocking call
+ * and does not guarantee the node will respond in any given time.
+ *
+ * @param node
+ * The network node to solicit a response
+ */
+ public void solicitStatusResponse(Node node);
+
/**
* Check whether the passed flow entry conflicts with the Container flows
*
* @param name
* the flow name
* @param n
- * the netwrok node identifier
+ * the network node identifier
* @return the {@code FlowConfig} object
*/
public FlowConfig getStaticFlow(String name, Node n);
* otherwise
*/
public void policyUpdate(String policyName, boolean add);
+
+ /**
+ * Inform listeners that the network node has notified us about a failure in
+ * executing the controller generated asynchronous request identified by the
+ * passed unique id.
+ *
+ * @param requestId
+ * the unique id associated with the request which failed to be
+ * executed on the network node
+ * @param error
+ * the string describing the error reported by the network node
+ */
+ public void requestFailed(long requestId, String error);
+
}
*
* @param flowEntry
* the original flow entry application requested to add
- * @return
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status addEntry(FlowEntry flowEntry) {
+ private Status addEntry(FlowEntry flowEntry, boolean async) {
+
// Sanity Check
if (flowEntry == null || flowEntry.getNode() == null) {
String msg = "Invalid FlowEntry";
// Try to install an entry at the time
Status error = new Status(null, null);
+ Status succeded = null;
boolean oneSucceded = false;
- for (FlowEntryInstall installEntry : toInstallList) {
+ for (FlowEntryInstall installEntry : toInstallSafe) {
// Install and update database
- Status ret = addEntriesInternal(installEntry);
+ Status ret = addEntriesInternal(installEntry, async);
if (ret.isSuccess()) {
oneSucceded = true;
+ /*
+ * The first successful status response will be returned
+ * For the asynchronous call, we can discard the container flow
+ * complication for now and assume we will always deal with
+ * one flow only per request
+ */
+ succeded = ret;
} else {
error = ret;
log.warn("Failed to install the entry: {}. The failure is: {}",
}
}
- return (oneSucceded) ? new Status(StatusCode.SUCCESS, null) : error;
+ return (oneSucceded) ? succeded : error;
}
/**
*
* @param currentFlowEntry
* @param newFlowEntry
- * @return Success or error string
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
private Status modifyEntry(FlowEntry currentFlowEntry,
- FlowEntry newFlowEntry) {
+ FlowEntry newFlowEntry, boolean async) {
+
Status retExt;
// Sanity checks
* So, for the above two cases, to simplify, let's decouple the modify
* in: 1) remove current entries 2) install new entries
*/
+ Status succeeded = null;
boolean decouple = false;
if (installedList.size() != toInstallList.size()) {
log.info("Modify: New flow entry does not satisfy the same "
if (decouple) {
// Remove current entries
for (FlowEntryInstall currEntry : installedList) {
- this.removeEntryInternal(currEntry);
+ this.removeEntryInternal(currEntry, async);
}
// Install new entries
for (FlowEntryInstall newEntry : toInstallSafe) {
- this.addEntriesInternal(newEntry);
+ succeeded = this.addEntriesInternal(newEntry, async);
}
} else {
/*
* fails, we need to stop, restore the already modified entries, and
* declare failure.
*/
- Status retModify;
+ Status retModify = null;
int i = 0;
int size = toInstallList.size();
while (i < size) {
// Modify and update database
retModify = modifyEntryInternal(installedList.get(i),
- toInstallList.get(i));
+ toInstallList.get(i), async);
if (retModify.isSuccess()) {
i++;
} else {
while (j < i) {
log.info("Attempting to restore initial entries");
retExt = modifyEntryInternal(toInstallList.get(i),
- installedList.get(i));
+ installedList.get(i), async);
if (retExt.isSuccess()) {
j++;
} else {
return new Status(StatusCode.INTERNALERROR, msg);
}
}
+ succeeded = retModify;
}
- return new Status(StatusCode.SUCCESS, null);
+ /*
+ * The first successful status response will be returned.
+ * For the asynchronous call, we can discard the container flow
+ * complication for now and assume we will always deal with
+ * one flow only per request
+ */
+ return succeeded;
}
/**
*
* @param currentEntries
* @param newEntries
- * @return
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
private Status modifyEntryInternal(FlowEntryInstall currentEntries,
- FlowEntryInstall newEntries) {
+ FlowEntryInstall newEntries, boolean async) {
// Modify the flow on the network node
- Status status = programmer.modifyFlow(currentEntries.getNode(),
- currentEntries.getInstall().getFlow(), newEntries.getInstall()
- .getFlow());
+ Status status = (async)?
+ programmer.modifyFlowAsync(currentEntries.getNode(),
+ currentEntries.getInstall().getFlow(), newEntries.getInstall()
+ .getFlow()) :
+ programmer.modifyFlow(currentEntries.getNode(),
+ currentEntries.getInstall().getFlow(), newEntries.getInstall()
+ .getFlow());
+
if (!status.isSuccess()) {
log.warn(
newEntries.getInstall());
// Update DB
+ newEntries.setRequestId(status.getRequestId());
updateLocalDatabase(currentEntries, false);
updateLocalDatabase(newEntries, true);
* (entry or node not present), it return successfully
*
* @param flowEntry
- * @return
+ * the flow entry to remove
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status removeEntry(FlowEntry flowEntry) {
+ private Status removeEntry(FlowEntry flowEntry, boolean async) {
Status error = new Status(null, null);
// Sanity Check
flowEntry.clone(), container.getContainerFlows());
Set<FlowEntryInstall> flowsOnNode = nodeFlows.get(flowEntry.getNode());
+ Status succeeded = null;
boolean atLeastOneRemoved = false;
for (FlowEntryInstall entry : installedList) {
if (flowsOnNode == null) {
log.debug(logMsg, flowEntry);
if (installedList.size() == 1) {
// If we had only one entry to remove, we are done
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
} else {
continue;
}
}
// Remove and update DB
- Status ret = removeEntryInternal(entry);
+ Status ret = removeEntryInternal(entry, async);
if (!ret.isSuccess()) {
error = ret;
return error;
}
} else {
+ succeeded = ret;
atLeastOneRemoved = true;
}
}
* 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) ? succeeded : error;
}
/**
* validity checks are passed
*
* @param entry
- * the FlowEntryInstall
- * @return "Success" or error string
+ * the flow entry to remove
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status removeEntryInternal(FlowEntryInstall entry) {
+ private Status removeEntryInternal(FlowEntryInstall entry, boolean async) {
// Mark the entry to be deleted (for CC just in case we fail)
entry.toBeDeleted();
// Remove from node
- Status status = programmer.removeFlow(entry.getNode(), entry
- .getInstall().getFlow());
+ Status status = (async)?
+ programmer.removeFlowAsync(entry.getNode(), entry
+ .getInstall().getFlow()) :
+ programmer.removeFlow(entry.getNode(), entry
+ .getInstall().getFlow());
+
if (!status.isSuccess()) {
log.warn(
entry.getInstall(), status.getDescription());
return status;
}
- log.info("Removed {}", entry.getInstall());
+ log.trace("Removed {}", entry.getInstall());
// Update DB
updateLocalDatabase(entry, false);
* whether this flow would conflict or overwrite an existing one.
*
* @param entry
- * the FlowEntryInstall
- * @return "Success" or error string
+ * the flow entry to install
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status addEntriesInternal(FlowEntryInstall entry) {
+ private Status addEntriesInternal(FlowEntryInstall entry, boolean async) {
// Install the flow on the network node
- Status status = programmer.addFlow(entry.getNode(), entry.getInstall()
- .getFlow());
+ Status status = (async)?
+ programmer.addFlow(entry.getNode(), entry.getInstall()
+ .getFlow()) :
+ programmer.addFlowAsync(entry.getNode(), entry.getInstall()
+ .getFlow());
+
if (!status.isSuccess()) {
log.warn(
return status;
}
- log.info("Added {}", entry.getInstall());
+ log.trace("Added {}", entry.getInstall());
// Update DB
+ entry.setRequestId(status.getRequestId());
updateLocalDatabase(entry, true);
return status;
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, flowEntry);
} else {
- status = addEntry(flowEntry);
+ status = addEntry(flowEntry, false);
+ }
+ return status;
+ }
+
+ @Override
+ public Status installFlowEntryAsync(FlowEntry flowEntry) {
+ Status status;
+ if (inContainerMode) {
+ String msg = "Controller in container mode: Install Refused";
+ status = new Status(StatusCode.NOTACCEPTABLE, msg);
+ log.warn(msg);
+ } else {
+ status = addEntry(flowEntry, true);
}
return status;
}
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, entry);
} else {
- status = removeEntry(entry);
+ status = removeEntry(entry, false);
}
return status;
}
+ @Override
+ public Status uninstallFlowEntryAsync(FlowEntry flowEntry) {
+ Status status;
+ if (inContainerMode) {
+ String msg = "Controller in container mode: Uninstall Refused";
+ status = new Status(StatusCode.NOTACCEPTABLE, msg);
+ log.warn(msg);
+ } else {
+ status = removeEntry(flowEntry, true);
+ }
+ return status;
+ }
+
@Override
public Status modifyFlowEntry(FlowEntry currentFlowEntry,
FlowEntry newFlowEntry) {
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, newFlowEntry);
} else {
- status = modifyEntry(currentFlowEntry, newFlowEntry);
+ status = modifyEntry(currentFlowEntry, newFlowEntry, false);
+ }
+ return status;
+ }
+
+ @Override
+ public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone) {
+ Status status = null;
+ if (inContainerMode) {
+ String msg = "Controller in container mode: Modify Refused";
+ status = new Status(StatusCode.NOTACCEPTABLE, msg);
+ log.warn(msg);
+ } else {
+ status = modifyEntry(current, newone, true);
}
return status;
}
}
}
+ @Override
+ public Status modifyOrAddFlowEntryAsync(FlowEntry newone) {
+ /*
+ * 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
+ */
+ FlowEntryInstall currentFlowEntries = findMatch(newone, true);
+
+ if (currentFlowEntries != null) {
+ return modifyFlowEntryAsync(currentFlowEntries.getOriginal(),
+ newone);
+ } else {
+ return installFlowEntry(newone);
+ }
+ }
+
+
/**
* 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,
// Remove the old couples. No validity checks to be run, use the
// internal remove
for (FlowEntryInstall oldCouple : oldCouples) {
- this.removeEntryInternal(oldCouple);
+ this.removeEntryInternal(oldCouple, false);
}
// Reinstall the original flow entries, via the regular path: new
// cFlow merge + validations
for (NodeConnector dstPort : portList) {
newFlowEntry.getFlow().addAction(new Output(dstPort));
}
- Status error = modifyEntry(currentFlowEntry, newFlowEntry);
+ Status error = modifyEntry(currentFlowEntry, newFlowEntry, false);
if (error.isSuccess()) {
log.info("Ports {} added to FlowEntry {}", portList,
flowName);
Action action = new Output(dstPort);
newFlowEntry.getFlow().removeAction(action);
}
- Status status = modifyEntry(currentFlowEntry, newFlowEntry);
+ Status status = modifyEntry(currentFlowEntry, newFlowEntry, false);
if (status.isSuccess()) {
log.info("Ports {} removed from FlowEntry {}", portList,
flowName);
newFlowEntry.getFlow().addAction(new Output(outPort));
// Modify on network node
- Status status = modifyEntry(currentFlowEntry, newFlowEntry);
+ Status status = modifyEntry(currentFlowEntry, newFlowEntry, false);
if (status.isSuccess()) {
log.info("Output port replaced with {} for flow {} on node {}",
// Program hw
if (config.installInHw()) {
FlowEntry entry = config.getFlowEntry();
- status = this.addEntry(entry);
+ status = this.addEntry(entry, false);
if (!status.isSuccess()) {
config.setStatus(status.getDescription());
if (!restore) {
portGroupChanged(pgconfig, existingData, true);
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
private void addStaticFlowsToSwitch(Node node) {
if (config.installInHw()
&& !config.getStatus().equals(
StatusCode.SUCCESS.toString())) {
- Status status = this.addEntry(config.getFlowEntry());
+ Status status = this.addEntry(config.getFlowEntry(), false);
config.setStatus(status.getDescription());
}
}
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(), false);
// Update configuration database if programming was successful
if (status.isSuccess()) {
staticFlows.remove(entry.getKey());
}
if (!entry.isPortGroupEnabled()) {
// Program the network node
- status = this.removeEntry(entry.getFlowEntry());
+ status = this.removeEntry(entry.getFlowEntry(), false);
}
// Update configuration database if programming was successful
if (status.isSuccess()) {
Status status = new Status(StatusCode.SUCCESS, "Saved in config");
if (oldFlowConfig.installInHw()) {
status = this.modifyEntry(oldFlowConfig.getFlowEntry(),
- newFlowConfig.getFlowEntry());
+ newFlowConfig.getFlowEntry(), false);
}
// Update configuration database if programming was successful
FlowConfig conf = entry.getValue();
if (conf.isByNameAndNodeIdEqual(config)) {
// Program the network node
- Status status = new Status(StatusCode.SUCCESS, null);
+ Status status = new Status(StatusCode.SUCCESS);
if (conf.installInHw()) {
- status = this.removeEntry(conf.getFlowEntry());
+ status = this.removeEntry(conf.getFlowEntry(), false);
} else {
- status = this.addEntry(conf.getFlowEntry());
+ status = this.addEntry(conf.getFlowEntry(), false);
}
if (!status.isSuccess()) {
conf.setStatus(status.getDescription());
// Now remove the entries
for (FlowEntry flowEntry : inactiveFlows) {
- Status status = this.removeEntry(flowEntry);
+ Status status = this.removeEntry(flowEntry, false);
if (!status.isSuccess()) {
- log.warn("Failed to remove entry: {}. The failure is: {}"
- + flowEntry, status.getDescription());
+ log.warn("Failed to remove entry: {}. The failure is: {}",
+ flowEntry, status.getDescription());
}
}
}
log.info("Reinstalling all inactive flows");
for (FlowEntry flowEntry : this.inactiveFlows) {
- Status status = this.addEntry(flowEntry);
+ Status status = this.addEntry(flowEntry, false);
if (!status.isSuccess()) {
- log.warn("Failed to install entry: {}. The failure is: {}"
- + flowEntry, status.getDescription());
+ log.warn("Failed to install entry: {}. The failure is: {}",
+ flowEntry, status.getDescription());
}
}
@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: {} Data: {}", config, portGroupData);
Map<Node, PortGroup> existingData = portGroupData.get(config);
if (existingData != null) {
for (Map.Entry<Node, PortGroup> entry : data.entrySet()) {
@Override
public void flowErrorReported(Node node, long rid, Object err) {
- log.error("Got error {} for message rid {} from node {}", new Object[] {
- err, rid, node });
+ log.trace("Got error {} for message rid {} from node {}",
+ new Object[] {err, rid, node });
+ /*
+ * If this was for a flow install, remove the corresponding entry
+ * from the software view. If it was a Looking for the rid going through the
+ * software database.
+ * TODO: A more efficient rid <-> FlowEntryInstall mapping will
+ * have to be added in future
+ */
+ Set<FlowEntryInstall> entries = nodeFlows.get(node);
+ if (entries != null) {
+ FlowEntryInstall target = null;
+ for (FlowEntryInstall entry : entries) {
+ if (entry.getRequestId() == rid) {
+ target = entry;
+ break;
+ }
+ }
+ if (target != null) {
+ // This was a flow install, update database
+ this.updateLocalDatabase(target, false);
+ }
+ }
+
+ // Notify listeners
+ if (frmAware != null) {
+ synchronized (frmAware) {
+ for (IForwardingRulesManagerAware frma : frmAware) {
+ try {
+ frma.requestFailed(rid, err.toString());
+ } catch (Exception e) {
+ log.warn("Failed to notify {}", frma);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void solicitStatusResponse(Node node) {
+ if (this.programmer != null) {
+ programmer.sendBarrierMessage(node);
+ }
}
+
}
import org.osgi.service.log.LogEntry;
import java.util.Enumeration;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.ServiceReference;
*/
Thread.setDefaultUncaughtExceptionHandler(new org.opendaylight.
controller.logging.bridge.internal.UncaughtExceptionHandler());
+
+ /*
+ * Install the Shutdown handler. This will intercept SIGTERM signal and
+ * close the system bundle. This allows for a graceful closing of OSGI
+ * framework.
+ */
+
+ Runtime.getRuntime().addShutdownHook(new shutdownHandler(context));
} else {
this.log.error("Cannot register the LogListener because "
+ "cannot retrieve LogReaderService");
this.listener = null;
this.log = null;
}
+
+ private class shutdownHandler extends Thread {
+ BundleContext bundlecontext;
+ public shutdownHandler(BundleContext ctxt) {
+ this.bundlecontext = ctxt;
+ }
+
+ public void run () {
+ try {
+ this.bundlecontext.getBundle(0).stop();
+ log.debug("shutdown handler thread called");
+ } catch (BundleException e) {
+ log.debug("Bundle couldn't be stopped");
+ }
+ }
+ }
+
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
private AtomicInteger switchInstanceNumber;
/*
- * this thread monitors the switchEvents queue for new incoming events from switch
+ * this thread monitors the switchEvents queue for new incoming events from
+ * switch
*/
private class EventHandler implements Runnable {
@Override
SwitchEvent ev = switchEvents.take();
SwitchEvent.SwitchEventType eType = ev.getEventType();
ISwitch sw = ev.getSwitch();
- if (eType != SwitchEvent.SwitchEventType.SWITCH_MESSAGE) {
- //logger.debug("Received " + ev.toString() + " from " + sw.toString());
- }
switch (eType) {
case SWITCH_ADD:
Long sid = sw.getId();
ISwitch existingSwitch = switches.get(sid);
if (existingSwitch != null) {
- logger.info(" Replacing existing "
- + existingSwitch.toString() + " with New "
- + sw.toString());
+ logger.info("Replacing existing {} with New {}",
+ existingSwitch.toString(), sw.toString());
disconnectSwitch(existingSwitch);
}
switches.put(sid, sw);
}
break;
default:
- logger.error("unknow switch event " + eType.ordinal());
+ logger.error("Unknown switch event {}", eType.ordinal());
}
} catch (InterruptedException e) {
switchEvents.clear();
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
public void init() {
- logger.debug("OpenFlowCore init");
+ logger.debug("Initializing!");
this.switches = new ConcurrentHashMap<Long, ISwitch>();
this.switchEvents = new LinkedBlockingQueue<SwitchEvent>();
this.messageListeners = new ConcurrentHashMap<OFType, IMessageListener>();
}
/**
- * 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
+ *
*/
public void start() {
- logger.debug("OpenFlowCore start() is called");
+ logger.debug("Starting!");
/*
* start a thread to handle event coming from the switch
*/
try {
controllerIO.start();
} catch (IOException ex) {
- logger.error("Caught exception: " + ex + " during start");
+ logger.error("Caught exception while starting:", ex);
}
}
-
+
/**
- * 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
+ *
*/
public void stop() {
for (Iterator<Entry<Long, ISwitch>> it = switches.entrySet().iterator(); it
}
switchEventThread.interrupt();
try {
- controllerIO.shutDown();
+ controllerIO.shutDown();
} catch (IOException ex) {
- logger.error("Caught exception: " + ex + " during stop");
+ logger.error("Caught exception while stopping:", ex);
}
}
/**
- * 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.
+ *
*/
public void destroy() {
}
public void addMessageListener(OFType type, IMessageListener listener) {
IMessageListener currentListener = this.messageListeners.get(type);
if (currentListener != null) {
- logger.warn(type.toString() + " already listened by "
- + currentListener.toString());
+ logger.warn("{} is already listened by {}", type.toString(),
+ currentListener.toString());
}
this.messageListeners.put(type, listener);
- logger.debug(type.toString() + " is now listened by "
- + listener.toString());
+ logger.debug("{} is now listened by {}", type.toString(),
+ listener.toString());
}
@Override
public void removeMessageListener(OFType type, IMessageListener listener) {
IMessageListener currentListener = this.messageListeners.get(type);
if ((currentListener != null) && (currentListener == listener)) {
+ logger.debug("{} listener {} is Removed", type.toString(),
+ listener.toString());
this.messageListeners.remove(type);
}
}
@Override
public void addSwitchStateListener(ISwitchStateListener listener) {
if (this.switchStateListener != null) {
- logger.warn(this.switchStateListener.toString()
- + "already listened to switch events");
+ logger.warn("Switch events are already listened by {}",
+ this.switchStateListener.toString());
}
this.switchStateListener = listener;
- logger.debug(listener.toString() + " now listens to switch events");
+ logger.debug("Switch events are now listened by {}",
+ listener.toString());
}
@Override
public void removeSwitchStateListener(ISwitchStateListener listener) {
if ((this.switchStateListener != null)
&& (this.switchStateListener == listener)) {
+ logger.debug("SwitchStateListener {} is Removed",
+ listener.toString());
this.switchStateListener = null;
}
}
SwitchHandler switchHandler = new SwitchHandler(this, sc,
instanceName);
switchHandler.start();
- logger.info(instanceName + " connected: " + sc.toString());
+ if (sc.isConnected()) {
+ logger.info("Switch:{} is connected to the Controller",
+ sc.socket().getRemoteSocketAddress()
+ .toString().split("/")[1]);
+ }
+
} catch (IOException e) {
return;
}
if (((SwitchHandler) sw).isOperational()) {
Long sid = sw.getId();
if (this.switches.remove(sid, sw)) {
- logger.warn(sw.toString() + " is disconnected");
+ logger.warn("{} is Disconnected", sw.toString());
notifySwitchDeleted(sw);
- } else {
- //logger.warn(sw.toString() + " has been replaced by " +
- // this.switches.get(sid));
}
}
((SwitchHandler) sw).stop();
}
}
- public void takeSwtichEventAdd(ISwitch sw) {
+ public void takeSwitchEventAdd(ISwitch sw) {
SwitchEvent ev = new SwitchEvent(
SwitchEvent.SwitchEventType.SWITCH_ADD, sw, null);
addSwitchEvent(ev);
while (iter.hasNext()) {
Long sid = iter.next();
Date date = switches.get(sid).getConnectedDate();
- String switchInstanceName = ((SwitchHandler) switches.get(sid)).getInstanceName();
+ String switchInstanceName = ((SwitchHandler) switches.get(sid))
+ .getInstanceName();
s.append(switchInstanceName + "/" + HexString.toHexString(sid)
+ " connected since " + date.toString() + "\n");
}
@Override
public String getHelp() {
StringBuffer help = new StringBuffer();
- help.append("-- Open Flow Controller --\n");
+ help.append("---Open Flow Controller---\n");
help.append("\t controllerShowSwitches\n");
help.append("\t controllerReset\n");
help.append("\t controllerShowConnConfig\n");
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
try {
openFlowPort = Short.decode(portString).shortValue();
} catch (NumberFormatException e) {
- logger.warn("Invalid port:" + portString + ", use default("
- + openFlowPort + ")");
+ logger.warn("Invalid port:{}, use default({})", portString,
+ openFlowPort);
}
}
}
SelectionKey skey = selectedKeys.next();
selectedKeys.remove();
if (skey.isValid() && skey.isAcceptable()) {
- ((Controller) listener).handleNewConnection(selector,
- serverSelectionKey);
+ ((Controller) listener).handleNewConnection(
+ selector, serverSelectionKey);
}
}
} catch (Exception e) {
}
}, "ControllerI/O Thread");
controllerIOThread.start();
- logger.info("Controller is now listening on port " + openFlowPort);
+ logger.info("Controller is now listening on port {}", openFlowPort);
}
public void shutDown() throws IOException {
}
for (OFMessage msg : msgs) {
logger.trace("Message received: {}", msg.toString());
- /*
- * if ((msg.getType() != OFType.ECHO_REQUEST) && (msg.getType() !=
- * OFType.ECHO_REPLY)) { logger.debug(msg.getType().toString() +
- * " received from sw " + toString()); }
- */
this.lastMsgReceivedTimeStamp = System.currentTimeMillis();
OFType type = msg.getType();
switch (type) {
}
private void processPortStatusMsg(OFPortStatus msg) {
- // short portNumber = msg.getDesc().getPortNumber();
OFPhysicalPort port = msg.getDesc();
if (msg.getReason() == (byte) OFPortReason.OFPPR_MODIFY.ordinal()) {
updatePhysicalPort(port);
- // logger.debug("Port " + portNumber + " on " + toString() +
- // " modified");
} else if (msg.getReason() == (byte) OFPortReason.OFPPR_ADD.ordinal()) {
updatePhysicalPort(port);
- // logger.debug("Port " + portNumber + " on " + toString() +
- // " added");
} else if (msg.getReason() == (byte) OFPortReason.OFPPR_DELETE
.ordinal()) {
deletePhysicalPort(port);
- // logger.debug("Port " + portNumber + " on " + toString() +
- // " deleted");
}
}
reportSwitchStateChange(false);
} else {
// send a probe to see if the switch is still alive
- // logger.debug("Send idle probe (Echo Request) to "
- // + switchName());
+ logger.debug(
+ "Send idle probe (Echo Request) to {}",
+ toString());
probeSent = true;
OFMessage echo = factory
.getMessage(OFType.ECHO_REQUEST);
private void reportError(Exception e) {
if (e instanceof AsynchronousCloseException
|| e instanceof InterruptedException
- || e instanceof SocketException
- || e instanceof IOException) {
+ || e instanceof SocketException || e instanceof IOException) {
logger.debug("Caught exception {}", e.getMessage());
} else {
logger.warn("Caught exception ", e);
private void reportSwitchStateChange(boolean added) {
if (added) {
- ((Controller) core).takeSwtichEventAdd(this);
+ ((Controller) core).takeSwitchEventAdd(this);
} else {
((Controller) core).takeSwitchEventDelete(this);
}
.getValue()
| OFPortFeatures.OFPPF_1GB_HD
.getValue() | OFPortFeatures.OFPPF_10GB_FD
- .getValue()));
+ .getValue()));
}
private void deletePhysicalPort(OFPhysicalPort port) {
@Override
public String toString() {
- return ("["
- + this.socket.toString()
- + " SWID "
- + (isOperational() ? HexString.toHexString(this.sid)
- : "unkbown") + "]");
+ try {
+ return ("Switch:"
+ + socket.socket().getRemoteSocketAddress().toString().split("/")[1]
+ + " SWID:" + (isOperational() ? HexString
+ .toHexString(this.sid) : "unknown"));
+ } catch (Exception e) {
+ return (isOperational() ? HexString.toHexString(this.sid)
+ : "unknown");
+ }
+
}
@Override
}
/**
- * Sends synchronous Barrier message
+ * Sends synchronous Barrier message
*/
@Override
public Object sendBarrierMessage() {
OFBarrierRequest barrierMsg = new OFBarrierRequest();
- return syncSend(barrierMsg);
+ return syncSend(barrierMsg);
}
-
+
/**
* This method returns the switch liveness timeout value. If controller did
* not receive any message from the switch for such a long period,
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.util.List;
+import org.opendaylight.controller.sal.reader.NodeDescription;
import org.openflow.protocol.statistics.OFDescriptionStatistics;
import org.openflow.protocol.statistics.OFStatistics;
-
-import org.opendaylight.controller.sal.reader.NodeDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Utility class for converting openflow description statistics
- * into SAL NodeDescription object
- *
- *
- *
+ * Utility class for converting openflow description statistics into SAL
+ * NodeDescription object
+ *
+ *
+ *
*/
public class DescStatisticsConverter {
+ private static final Logger log = LoggerFactory
+ .getLogger(DescStatisticsConverter.class);
NodeDescription hwDesc;
OFDescriptionStatistics ofDesc;
hwDesc.setDescription(ofDesc.getDatapathDescription());
hwDesc.setSerialNumber(ofDesc.getSerialNumber());
}
+ log.trace("OFDescriptionStatistics: {}", ofDesc);
+ log.trace("NodeDescription: {}", hwDesc);
return hwDesc;
}
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFVendor;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionDataLayerDestination;
-import org.openflow.protocol.action.OFActionDataLayerSource;
-import org.openflow.protocol.action.OFActionNetworkLayerAddress;
-import org.openflow.protocol.action.OFActionNetworkLayerDestination;
-import org.openflow.protocol.action.OFActionNetworkLayerSource;
-import org.openflow.protocol.action.OFActionNetworkTypeOfService;
-import org.openflow.protocol.action.OFActionOutput;
-import org.openflow.protocol.action.OFActionStripVirtualLan;
-import org.openflow.protocol.action.OFActionTransportLayer;
-import org.openflow.protocol.action.OFActionTransportLayerDestination;
-import org.openflow.protocol.action.OFActionTransportLayerSource;
-import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
-import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
-import org.openflow.util.U16;
-import org.openflow.util.U32;
-
import org.opendaylight.controller.sal.action.Action;
import org.opendaylight.controller.sal.action.ActionType;
import org.opendaylight.controller.sal.action.Controller;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFVendor;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionDataLayerDestination;
+import org.openflow.protocol.action.OFActionDataLayerSource;
+import org.openflow.protocol.action.OFActionNetworkLayerAddress;
+import org.openflow.protocol.action.OFActionNetworkLayerDestination;
+import org.openflow.protocol.action.OFActionNetworkLayerSource;
+import org.openflow.protocol.action.OFActionNetworkTypeOfService;
+import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.protocol.action.OFActionStripVirtualLan;
+import org.openflow.protocol.action.OFActionTransportLayer;
+import org.openflow.protocol.action.OFActionTransportLayerDestination;
+import org.openflow.protocol.action.OFActionTransportLayerSource;
+import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
+import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
+import org.openflow.util.U16;
+import org.openflow.util.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
public class FlowConverter {
protected static final Logger logger = LoggerFactory
- .getLogger(FlowConverter.class);
+ .getLogger(FlowConverter.class);
private Flow flow; // SAL Flow
private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match
private List<OFAction> actionsList; // OF 1.0 actions
ofMatch.setWildcards(U32.t(Long.valueOf(wildcards)));
}
}
-
+ logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(),
+ ofMatch);
return ofMatch;
}
}
}
}
+ logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(),
+ actionsList);
return actionsList;
}
}
}
}
+ logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
+ actionsList);
+ logger.trace("Openflow Mod Message: {}", fm);
return fm;
}
try {
ip = InetAddress.getByAddress(addr);
} catch (UnknownHostException e) {
- logger.error("",e);
+ logger.error("", e);
}
salAction = new SetNwSrc(ip);
} else if (ofAction instanceof OFActionNetworkLayerDestination) {
try {
ip = InetAddress.getByAddress(addr);
} catch (UnknownHostException e) {
- logger.error("",e);
+ logger.error("", e);
}
salAction = new SetNwDst(ip);
} else if (ofAction instanceof OFActionNetworkTypeOfService) {
// Create Flow
flow = new Flow(salMatch, salActionList);
}
+ logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
+ actionsList);
+ logger.trace("SAL Flow: {}", flow);
return flow;
}
package org.opendaylight.controller.protocol_plugin.openflow.internal;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
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.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NodeCreator;
-import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+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.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
}
if (result instanceof Boolean) {
return ((Boolean) result == Boolean.TRUE) ? new Status(
- StatusCode.SUCCESS, null) : new Status(
+ StatusCode.SUCCESS, rid) : 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);
- 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.TIMEOUT, errorString(null,
action, "Request Timed Out"));
} else if (msg2 == null) {
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS, rid);
}
} else if (result instanceof OFError) {
return new Status(StatusCode.INTERNALERROR, errorString(
}
if (result instanceof Boolean) {
return ((Boolean) result == Boolean.TRUE) ? new Status(
- StatusCode.SUCCESS, null) : new Status(
+ StatusCode.SUCCESS, rid) : new Status(
StatusCode.TIMEOUT, errorString(null, action,
"Request Timed Out"));
} else if (result instanceof OFError) {
}
if (result instanceof Boolean) {
return ((Boolean) result == Boolean.TRUE) ? new Status(
- StatusCode.SUCCESS, null) : new Status(
+ StatusCode.SUCCESS, rid) : new Status(
StatusCode.TIMEOUT, errorString(null, action,
"Request Timed Out"));
} else if (result instanceof OFError) {
xid = errorMsg.getXid();
}
- long rid = getMessageRid(sw.getId(), xid);
+ Long rid = getMessageRid(sw.getId(), xid);
+ /*
+ * Null or zero requestId indicates that the error message is meant for
+ * a sync message. It will be handled by the sync message worker thread.
+ * Hence we are done here.
+ */
+ if ((rid == null) || (rid == 0)) {
+ return;
+ }
+
+ /*
+ * Notifies the caller that error has been reported for a previous flow
+ * programming request
+ */
for (Map.Entry<String, IFlowProgrammerNotifier> containerNotifier : flowProgrammerNotifiers
.entrySet()) {
IFlowProgrammerNotifier notifier = containerNotifier.getValue();
* The OF message xid
* @return The Request ID
*/
- public long getMessageRid(long swid, int xid) {
+ private Long getMessageRid(long swid, Integer xid) {
+ Long rid = null;
+
+ if (xid == null) {
+ return rid;
+ }
+
Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
- long rid = 0;
-
if (swxid2rid != null) {
rid = swxid2rid.get(xid);
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.util.List;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsReply;
-import org.openflow.protocol.statistics.OFFlowStatisticsReply;
-import org.openflow.protocol.statistics.OFStatistics;
-
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.controller.sal.reader.FlowOnNode;
+import org.openflow.protocol.statistics.OFFlowStatisticsReply;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Converts an openflow list of flow statistics in a SAL list of FlowOnNode objects
- *
- *
- *
+ * Converts an openflow list of flow statistics in a SAL list of FlowOnNode
+ * objects
+ *
+ *
+ *
*/
public class FlowStatisticsConverter {
+ private static final Logger log = LoggerFactory
+ .getLogger(FlowStatisticsConverter.class);
private List<OFStatistics> ofStatsList;
private List<FlowOnNode> flowOnNodeList;
if (statsList == null) {// || statsList.isEmpty()) {
this.ofStatsList = new ArrayList<OFStatistics>(1); // dummy list
} else {
- this.ofStatsList = statsList; //new ArrayList<OFStatistics>(statsList);
+ this.ofStatsList = statsList; // new
+ // ArrayList<OFStatistics>(statsList);
}
this.flowOnNodeList = null;
}
flowOnNodeList.add(flowOnNode);
}
}
+ log.trace("OFStatistics: {} FlowOnNode: {}", ofStatsList,
+ flowOnNodeList);
return flowOnNodeList;
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.slf4j.LoggerFactory;
/**
- * It periodically polls the different OF statistics from the OF switches
- * and caches them for quick retrieval for the above layers' modules
- * It also provides an API to directly query the switch about the statistics
+ * It periodically polls the different OF statistics from the OF switches and
+ * caches them for quick retrieval for the above layers' modules It also
+ * provides an API to directly query the switch about the statistics
*/
public class OFStatisticsManager implements IOFStatisticsManager,
IInventoryShimExternalListener, CommandProvider {
private Timer statisticsTimer;
private TimerTask statisticsTimerTask;
private ConcurrentMap<Long, Boolean> switchSupportsVendorExtStats;
- private Map<Long, Map<Short, TxRates>> txRates; // Per port sampled (every portStatsPeriod) transmit rate
+ private Map<Long, Map<Short, TxRates>> txRates; // Per port sampled (every
+ // portStatsPeriod) transmit
+ // rate
private Set<IStatisticsListener> descriptionListeners;
/**
- * The object containing the latest factoredSamples tx rate samples
- * for a given switch port
+ * The object containing the latest factoredSamples tx rate samples for a
+ * given switch port
*/
protected class TxRates {
- Deque<Long> sampledTxBytes; // contains the latest factoredSamples sampled transmitted bytes
+ Deque<Long> sampledTxBytes; // contains the latest factoredSamples
+ // sampled transmitted bytes
public TxRates() {
sampledTxBytes = new LinkedBlockingDeque<Long>();
public void update(Long txBytes) {
/*
- * Based on how many samples our average works on,
- * we might have to remove the oldest sample
+ * Based on how many samples our average works on, we might have to
+ * remove the oldest sample
*/
if (sampledTxBytes.size() == factoredSamples) {
sampledTxBytes.removeLast();
/**
* Returns the average transmit rate in bps
+ *
* @return the average transmit rate [bps]
*/
public long getAverageTxRate() {
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
void init() {
- flowStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
+ flowStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
descStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
portStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
dummyList = new ArrayList<OFStatistics>(1);
StatsRequest req = pendingStatsRequests.take();
acquireStatistics(req.switchId, req.type);
} catch (InterruptedException e) {
- log.warn("Flow Statistics Collector thread " +
- "interrupted");
+ log.warn("Flow Statistics Collector thread "
+ + "interrupted", e);
}
}
}
long switchId = switchPortStatsUpdated.take();
updatePortsTxRate(switchId);
} catch (InterruptedException e) {
- log.warn("TX Rate Updater thread interrupted");
+ log.warn("TX Rate Updater thread interrupted", e);
}
}
}
}
/**
- * 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() {
// Start managed timers
}
/**
- * 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() {
// Stop managed timers
}
public void setStatisticsListener(IStatisticsListener s) {
- this.descriptionListeners.add(s);
+ this.descriptionListeners.add(s);
}
-
+
public void unsetStatisticsListener(IStatisticsListener s) {
- if (s != null) {
- this.descriptionListeners.remove(s);
- }
+ if (s != null) {
+ this.descriptionListeners.remove(s);
+ }
}
-
+
private void registerWithOSGIConsole() {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
.getBundleContext();
}
private void addStatisticsTicks(Long switchId) {
- switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume switch supports Vendor extension stats
+ switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume
+ // switch
+ // supports
+ // Vendor
+ // extension
+ // stats
statisticsTimerTicks.put(switchId, new StatisticsTicks(true));
- log.info("Added Switch {} to target pool", HexString
- .toHexString(switchId.longValue()));
+ log.info("Added Switch {} to target pool",
+ HexString.toHexString(switchId.longValue()));
}
protected static class StatisticsTicks {
}
public boolean decrementFlowTicksIsZero() {
- // Please ensure no code is inserted between the if check and the flowStatisticsTicks reset
+ // Please ensure no code is inserted between the if check and the
+ // flowStatisticsTicks reset
if (--flowStatisticsTicks == 0) {
flowStatisticsTicks = statisticsTickNumber;
return true;
}
public boolean decrementDescTicksIsZero() {
- // Please ensure no code is inserted between the if check and the descriptionTicks reset
+ // Please ensure no code is inserted between the if check and the
+ // descriptionTicks reset
if (--descriptionTicks == 0) {
descriptionTicks = descriptionTickNumber;
return true;
}
public boolean decrementPortTicksIsZero() {
- // Please ensure no code is inserted between the if check and the descriptionTicks reset
+ // Please ensure no code is inserted between the if check and the
+ // descriptionTicks reset
if (--portStatisticsTicks == 0) {
portStatisticsTicks = portTickNumber;
return true;
}
private void printInfoMessage(String type, StatsRequest request) {
- log
- .info(
- type
- + " stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.",
- new Object[] { HexString.toHexString(request.switchId),
- pendingStatsRequests.size(),
- statisticsCollector.getState().toString() });
+ log.info(
+ "{} stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.",
+ new Object[] { type, HexString.toHexString(request.switchId),
+ pendingStatsRequests.size(),
+ statisticsCollector.getState().toString() });
}
protected void decrementTicks() {
Long switchId = entry.getKey();
if (clock.decrementFlowTicksIsZero() == true) {
request = (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) ? new StatsRequest(
- switchId, OFStatisticsType.VENDOR)
- : new StatsRequest(switchId, OFStatisticsType.FLOW);
- // If a request for this switch is already in the queue, skip to add this new request
+ switchId, OFStatisticsType.VENDOR) : new StatsRequest(
+ switchId, OFStatisticsType.FLOW);
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
if (!pendingStatsRequests.contains(request)
&& false == pendingStatsRequests.offer(request)) {
printInfoMessage("Flow", request);
if (clock.decrementDescTicksIsZero() == true) {
request = new StatsRequest(switchId, OFStatisticsType.DESC);
- // If a request for this switch is already in the queue, skip to add this new request
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
if (!pendingStatsRequests.contains(request)
&& false == pendingStatsRequests.offer(request)) {
printInfoMessage("Description", request);
if (clock.decrementPortTicksIsZero() == true) {
request = new StatsRequest(switchId, OFStatisticsType.PORT);
- // If a request for this switch is already in the queue, skip to add this new request
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
if (!pendingStatsRequests.contains(request)
&& false == pendingStatsRequests.offer(request)) {
printInfoMessage("Port", request);
}
private void removeStatsRequestTasks(Long switchId) {
- log.info("Cleaning Statistics database for switch "
- + HexEncode.longToHexString(switchId));
- // To be safe, let's attempt removal of both VENDOR and FLOW request. It does not hurt
+ log.info("Cleaning Statistics database for switch {}",
+ HexEncode.longToHexString(switchId));
+ // To be safe, let's attempt removal of both VENDOR and FLOW request. It
+ // does not hurt
pendingStatsRequests.remove(new StatsRequest(switchId,
OFStatisticsType.VENDOR));
pendingStatsRequests.remove(new StatsRequest(switchId,
statisticsTimerTicks.remove(switchId);
removeStatsRequestTasks(switchId);
flowStatistics.remove(switchId);
- log.info("Statistics removed for switch "
- + HexString.toHexString(switchId));
+ log.info("Statistics removed for switch {}",
+ HexString.toHexString(switchId));
}
private void acquireStatistics(Long switchId, OFStatisticsType statType) {
|| (statType == OFStatisticsType.VENDOR)) {
flowStatistics.put(switchId, values);
} else if (statType == OFStatisticsType.DESC) {
- // Notify who may be interested in a description change
- notifyDescriptionListeners(switchId, values);
-
+ // Notify who may be interested in a description change
+ notifyDescriptionListeners(switchId, values);
+
// Overwrite cache
descStatistics.put(switchId, values);
} else if (statType == OFStatisticsType.PORT) {
// Overwrite cache with new port statistics for this switch
portStatistics.put(switchId, values);
- // Wake up the thread which maintains the TX byte counters for each port
+ // Wake up the thread which maintains the TX byte counters for
+ // each port
switchPortStatsUpdated.offer(switchId);
}
}
}
private void notifyDescriptionListeners(Long switchId,
- List<OFStatistics> values) {
- for (IStatisticsListener l : this.descriptionListeners) {
- l.descriptionRefreshed(switchId,
- ((OFDescriptionStatistics)values.get(0)));
- }
+ List<OFStatistics> values) {
+ for (IStatisticsListener l : this.descriptionListeners) {
+ l.descriptionRefreshed(switchId,
+ ((OFDescriptionStatistics) values.get(0)));
+ }
}
-
+
/*
* Generic function to get the statistics form a OF switch
*/
match.setWildcards(0xffffffff);
} else if (!(target instanceof OFMatch)) {
// Malformed request
- log.warn("Invalid target type for Flow stats request: "
- + target.getClass());
+ log.warn("Invalid target type for Flow stats request: {}",
+ target.getClass());
return null;
} else {
// Specific flow request
targetPort = (short) OFPort.OFPP_NONE.getValue();
} else if (!(target instanceof Short)) {
// Malformed request
- log.warn("Invalid target type for Port stats request: "
- + target.getClass());
+ log.warn("Invalid target type for Port stats request: {}",
+ target.getClass());
return null;
} else {
// Specific port request
log.warn("Request Timed Out for ({}) from switch {}", type,
HexString.toHexString(switchId));
} else if (result instanceof OFError) {
- log.warn("Switch {} failed to handle ({}) stats request: "
- + Utils.getOFErrorString((OFError) result), HexString
- .toHexString(switchId), type);
+ log.warn("Switch {} failed to handle ({}) stats request: {}",
+ new Object[] { HexString.toHexString(switchId), type,
+ Utils.getOFErrorString((OFError) result) });
if (this.switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) {
- log
- .warn(
- "Switching back to regular Flow stats requests for switch {}",
- HexString.toHexString(switchId));
+ log.warn(
+ "Switching back to regular Flow stats requests for switch {}",
+ HexString.toHexString(switchId));
this.switchSupportsVendorExtStats.put(switchId,
Boolean.FALSE);
}
List<OFStatistics> list = flowStatistics.get(switchId);
/*
- * Check on emptiness as interference between add and get is still
- * possible on the inner list (the concurrentMap entry's value)
+ * Check on emptiness as interference between add and get is still
+ * possible on the inner list (the concurrentMap entry's value)
*/
return (list == null || list.isEmpty()) ? this.dummyList
: (list.get(0) instanceof OFVendorStatistics) ? this
List<OFStatistics> statsList = flowStatistics.get(switchId);
/*
- * Check on emptiness as interference between add and get is still
- * possible on the inner list (the concurrentMap entry's value)
+ * Check on emptiness as interference between add and get is still
+ * possible on the inner list (the concurrentMap entry's value)
*/
if (statsList == null || statsList.isEmpty()) {
return this.dummyList;
if (statsList.get(0) instanceof OFVendorStatistics) {
/*
- * Caller could provide regular OF match when we
- * instead pull the vendor statistics from this node
- * Caller is not supposed to know whether this switch supports
- * vendor extensions statistics requests
+ * Caller could provide regular OF match when we instead pull the
+ * vendor statistics from this node Caller is not supposed to know
+ * whether this switch supports vendor extensions statistics
+ * requests
*/
V6Match targetMatch = (ofMatch instanceof V6Match) ? (V6Match) ofMatch
: new V6Match(ofMatch);
ByteBuffer data = ByteBuffer.allocate(length);
stat.writeTo(data);
data.rewind();
- log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}", HexString
- .toHexString(data.array()));
+ log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}",
+ HexString.toHexString(data.array()));
- int vendor = data.getInt(); //first 4 bytes is vendor id.
+ int vendor = data.getInt(); // first 4 bytes is vendor id.
if (vendor != V6StatsRequest.NICIRA_VENDOR_ID) {
- log
- .debug("Unexpected vendor id: 0x{}", Integer
- .toHexString(vendor));
+ log.warn("Unexpected vendor id: 0x{}", Integer.toHexString(vendor));
return null;
} else {
- //go ahead by 8 bytes which is 8 bytes of 0
- data.getLong(); //should be all 0's
- length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have been consumed
+ // go ahead by 8 bytes which is 8 bytes of 0
+ data.getLong(); // should be all 0's
+ length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have
+ // been consumed
}
V6StatsReply v6statsreply;
public List<OFStatistics> queryStatistics(Long switchId,
OFStatisticsType statType, Object target) {
/*
- * Caller does not know and it is not supposed to know whether
- * this switch supports vendor extension. We adjust the target for him
+ * Caller does not know and it is not supposed to know whether this
+ * switch supports vendor extension. We adjust the target for him
*/
if (statType == OFStatisticsType.FLOW) {
if (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) {
}
/*
- * InventoryShim replay for us all the switch addition which happened before we were brought up
+ * InventoryShim replay for us all the switch addition which happened before
+ * we were brought up
*/
@Override
public void updateNode(Node node, UpdateType type, Set<Property> props) {
}
/**
- * Update the cached port rates for this switch with the latest
- * retrieved port transmit byte count
+ * Update the cached port rates for this switch with the latest retrieved
+ * port transmit byte count
+ *
* @param switchId
*/
private synchronized void updatePortsTxRate(long switchId) {
public String getHelp() {
StringBuffer help = new StringBuffer();
help.append("---OF Statistics Manager utilities---\n");
- help.append("\t ofdumpstatsmgr - " +
- "Print Internal Stats Mgr db\n");
+ help.append("\t ofdumpstatsmgr - "
+ + "Print Internal Stats Mgr db\n");
return help.toString();
}
public void _ofdumpstatsmgr(CommandInterpreter ci) {
ci.println("Global Counter: " + counter);
- ci
- .println("Timer Ticks: "
- + prettyPrintSwitchMap(statisticsTimerTicks));
+ ci.println("Timer Ticks: " + prettyPrintSwitchMap(statisticsTimerTicks));
ci.println("PendingStatsQueue: " + pendingStatsRequests);
ci.println("PendingStatsQueue size: " + pendingStatsRequests.size());
ci.println("Stats Collector alive: " + statisticsCollector.isAlive());
String averageWindow = ci.nextArgument();
short seconds = 0;
if (averageWindow == null) {
- ci.println("Insert the length in seconds of the median " +
- "window for tx rate");
- ci.println("Current: " + factoredSamples * portTickNumber
- + " secs");
+ ci.println("Insert the length in seconds of the median "
+ + "window for tx rate");
+ ci.println("Current: " + factoredSamples * portTickNumber + " secs");
return;
}
try {
} catch (NumberFormatException e) {
ci.println("Invalid period.");
}
- OFStatisticsManager.factoredSamples = (short) (seconds/portTickNumber);
+ OFStatisticsManager.factoredSamples = (short) (seconds / portTickNumber);
ci.println("New: " + factoredSamples * portTickNumber + " secs");
}
public void _ofstatsmgrintervals(CommandInterpreter ci) {
String flowStatsInterv = ci.nextArgument();
String portStatsInterv = ci.nextArgument();
-
+
if (flowStatsInterv == null || portStatsInterv == null) {
ci.println("Usage: ostatsmgrintervals <fP> <pP> (in seconds)");
- ci.println("Current Values: fP=" + statisticsTickNumber +
- "s pP=" + portTickNumber + "s");
+ ci.println("Current Values: fP=" + statisticsTickNumber + "s pP="
+ + portTickNumber + "s");
return;
}
Short fP, pP;
try {
- fP = Short.parseShort(flowStatsInterv);
- pP = Short.parseShort(portStatsInterv);
+ fP = Short.parseShort(flowStatsInterv);
+ pP = Short.parseShort(portStatsInterv);
} catch (Exception e) {
- ci.println("Invalid format values: " + e.getMessage());
- return;
+ ci.println("Invalid format values: " + e.getMessage());
+ return;
}
- if (pP <= 1 || fP <=1) {
- ci.println("Invalid values. fP and pP have to be greater than 1.");
- return;
+ if (pP <= 1 || fP <= 1) {
+ ci.println("Invalid values. fP and pP have to be greater than 1.");
+ return;
}
-
+
statisticsTickNumber = fP;
portTickNumber = pP;
-
- ci.println("New Values: fP=" + statisticsTickNumber +
- "s pP=" + portTickNumber + "s");
+
+ ci.println("New Values: fP=" + statisticsTickNumber + "s pP="
+ + portTickNumber + "s");
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
package org.opendaylight.controller.protocol_plugin.openflow.internal;
-import org.openflow.protocol.OFPort;
-
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.openflow.protocol.OFPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Abstract class which provides the utilities for converting
- * the Openflow port number to the equivalent NodeConnector and vice versa
- *
- *
- *
+ * Abstract class which provides the utilities for converting the Openflow port
+ * number to the equivalent NodeConnector and vice versa
+ *
+ *
+ *
*/
public abstract class PortConverter {
- private static final int maxOFPhysicalPort =
- NetUtils.getUnsignedShort(OFPort.OFPP_MAX.getValue());
+ private static final Logger log = LoggerFactory
+ .getLogger(PortConverter.class);
+ private static final int maxOFPhysicalPort = NetUtils
+ .getUnsignedShort(OFPort.OFPP_MAX.getValue());
/**
* Converts the Openflow port number to the equivalent NodeConnector.
public static NodeConnector toNodeConnector(short ofPort, Node node) {
// Restore original OF unsigned 16 bits value for the comparison
int unsignedOFPort = NetUtils.getUnsignedShort(ofPort);
-
+ log.trace("Openflow port number signed: {} unsigned: {}", ofPort,
+ unsignedOFPort);
if (unsignedOFPort > maxOFPhysicalPort) {
if (ofPort == OFPort.OFPP_LOCAL.getValue()) {
return NodeConnectorCreator.createNodeConnector(
* Converts the NodeConnector to the equivalent Openflow port number
*/
public static short toOFPort(NodeConnector salPort) {
+ log.trace("SAL Port", salPort);
if (salPort.getType().equals(NodeConnectorIDType.SWSTACK)) {
return OFPort.OFPP_LOCAL.getValue();
- } else if (salPort.getType().equals(
- NodeConnectorIDType.HWPATH)) {
+ } else if (salPort.getType().equals(NodeConnectorIDType.HWPATH)) {
return OFPort.OFPP_NORMAL.getValue();
- } else if (salPort.getType().equals(
- NodeConnectorIDType.CONTROLLER)) {
+ } else if (salPort.getType().equals(NodeConnectorIDType.CONTROLLER)) {
return OFPort.OFPP_CONTROLLER.getValue();
}
return (Short) salPort.getID();
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.util.ArrayList;
import java.util.List;
-import org.openflow.protocol.statistics.OFPortStatisticsReply;
-import org.openflow.protocol.statistics.OFStatistics;
-
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
import org.opendaylight.controller.sal.utils.NodeCreator;
+import org.openflow.protocol.statistics.OFPortStatisticsReply;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Converts an openflow list of port statistics in a SAL list of
* NodeConnectorStatistics objects
- *
- *
- *
+ *
+ *
+ *
*/
public class PortStatisticsConverter {
+ private static final Logger log = LoggerFactory
+ .getLogger(PortStatisticsConverter.class);
private long switchId;
private List<OFStatistics> ofStatsList;
private List<NodeConnectorStatistics> ncStatsList;
.getReceiveFrameErrors());
NCStat.setReceiveOverRunErrorCount(ofPortStat
.getReceiveOverrunErrors());
- NCStat
- .setReceiveCRCErrorCount(ofPortStat
- .getReceiveCRCErrors());
+ NCStat.setReceiveCRCErrorCount(ofPortStat.getReceiveCRCErrors());
NCStat.setCollisionCount(ofPortStat.getCollisions());
this.ncStatsList.add(NCStat);
}
}
+ log.trace("OFStatistics: {} NodeConnectorStatistics: {}", ofStatsList,
+ ncStatsList);
return this.ncStatsList;
}
package org.opendaylight.controller.protocol_plugin.openflow.internal;
+import java.nio.ByteBuffer;
+
+import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error;
import org.openflow.protocol.OFError;
import org.openflow.protocol.OFError.OFBadActionCode;
import org.openflow.protocol.OFError.OFBadRequestCode;
public abstract class Utils {
public static String getOFErrorString(OFError error) {
+ // Handle VENDOR extension errors here
+ if (error.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) {
+ V6Error er = new V6Error(error);
+ byte[] b = error.getError();
+ ByteBuffer bb = ByteBuffer.allocate(b.length);
+ bb.put(b);
+ bb.rewind();
+ er.readFrom(bb);
+ return er.toString();
+ }
+
+ // Handle OF1.0 errors here
OFErrorType et = OFErrorType.values()[0xffff & error.getErrorType()];
String errorStr = "Error : " + et.toString();
switch (et) {
* Synchronously add a flow to the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to install
+ * @return The status of this request
*/
Status addFlow(Node node, Flow flow);
* Synchronously modify existing flow on the switch
*
* @param node
- * @param flow
+ * The target network node
+ * @param oldFlow
+ * The existing flow to modify
+ * @param newFlow
+ * The new flow to install
+ * @return The status of this request
*/
Status modifyFlow(Node node, Flow oldFlow, Flow newFlow);
* Synchronously remove the flow from the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to remove
+ * @return The status of this request
*/
Status removeFlow(Node node, Flow flow);
* Asynchronously add a flow to the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to install
+ * @return The status of this request containing the unique request id
*/
Status addFlowAsync(Node node, Flow flow);
* Asynchronously modify existing flow on the switch
*
* @param node
- * @param flow
+ * The target network node
+ * @param oldFlow
+ * The existing flow to modify
+ * @param newFlow
+ * The new flow to install
+ * @return The status of this request containing the unique request id
*/
Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow);
* Asynchronously remove the flow from the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to remove
+ * @return The status of this request containing the unique request id
*/
Status removeFlowAsync(Node node, Flow flow);
* Remove all flows present on the network node
*
* @param node
+ * The target network node
+ * @return The status of this request containing the unique request id
*/
Status removeAllFlows(Node node);
/**
- * Send synchronous Barrier message
+ * Send synchronous Barrier message
+ *
+ * Solicit the network node to report whether all the requests sent so far
+ * are completed. When this call is done, caller knows that all past flow
+ * operations requested to the node in asynchronous fashion were satisfied
+ * by the network node and that in case of any failure, a message was sent
+ * to the controller.
*
* @param node
+ * The network node to solicit
+ * @return The status of this request containing the unique request id
*/
Status sendBarrierMessage(Node node);
}
* a string which describes a failure reason (if any) in human readable form.
*/
public class Status {
- StatusCode code;
- String description;
+ private StatusCode code;
+ private String description;
+ private long requestId;
/**
* Generates an instance of the Status class. This is used as return code
this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
this.description = (description != null) ? description : this.code
.toString();
+ this.requestId = 0;
}
/**
this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
this.description = (description != null) ? description : this.code
.toString();
+ this.requestId = 0;
+ }
+
+ /**
+ * Generates an instance of the Status class to be used in case of
+ * asynchronous call. It is supposed to be created by the underlying
+ * infrastructure only when it was successful in allocating the asynchronous
+ * request id, hence caller should expect StatusCode to be successful.
+ *
+ * @param errorCode
+ * The status code. If passed as null, code will be stored as
+ * {@code StatusCode.UNDEFINED}
+ * @param requestId
+ * The request id set by underlying infrastructure for this
+ * request
+ */
+ public Status(StatusCode errorCode, long requestId) {
+ this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
+ this.description = (description != null) ? description : this.code
+ .toString();
+ this.requestId = requestId;
}
/**
return code == StatusCode.SUCCESS;
}
+ /**
+ * Return the request id assigned by underlying infrastructure in case of
+ * asynchronous request. In case of synchronous requests, the returned id
+ * is expected to be 0
+ *
+ * @return The request id assigned for this asynchronous request
+ */
+ public long getRequestId() {
+ return requestId;
+ }
+
@Override
public String toString() {
- return code + ": " + description;
+ return code + ": " + description + " (" + requestId + ")";
}
@Override
import org.opendaylight.controller.sal.action.SetNwDst;
import org.opendaylight.controller.sal.core.ConstructionException;
import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector;
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.IPluginOutFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.sal.utils.EtherTypes;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
+++ /dev/null
-***************
-*** 29,35 ****
- import org.opendaylight.controller.switchmanager.SwitchConfig;
- import org.opendaylight.controller.usermanager.IUserManager;
- import org.opendaylight.controller.web.IOneWeb;
-- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
---- 31,36 ----
- import org.opendaylight.controller.switchmanager.SwitchConfig;
- import org.opendaylight.controller.usermanager.IUserManager;
- import org.opendaylight.controller.web.IOneWeb;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
-***************
-*** 182,189 ****
- @RequestMapping(value = "/flow", method = RequestMethod.POST)
- @ResponseBody
- public String actionFlow(@RequestParam(required = true) String action,
-- @RequestParam(required = false) String body, @RequestParam(required = true) String nodeId) {
-- if (!authorize(UserLevel.NETWORKADMIN)) {
- return "Operation not authorized";
- }
-
---- 183,190 ----
- @RequestMapping(value = "/flow", method = RequestMethod.POST)
- @ResponseBody
- public String actionFlow(@RequestParam(required = true) String action,
-+ @RequestParam(required = false) String body, @RequestParam(required = true) String nodeId, HttpServletRequest request) {
-+ if (!authorize(UserLevel.NETWORKADMIN, request)) {
- return "Operation not authorized";
- }
-
-***************
-*** 206,213 ****
- @RequestMapping(value = "/flow/{nodeId}/{name}", method = RequestMethod.POST)
- @ResponseBody
- public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name,
-- @RequestParam(required = true) String action) {
-- if (!authorize(UserLevel.NETWORKADMIN)) { return "Operation not authorized"; }
-
- IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
- .getInstance(IForwardingRulesManager.class, "default", this);
---- 207,214 ----
- @RequestMapping(value = "/flow/{nodeId}/{name}", method = RequestMethod.POST)
- @ResponseBody
- public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name,
-+ @RequestParam(required = true) String action, HttpServletRequest request) {
-+ if (!authorize(UserLevel.NETWORKADMIN, request)) { return "Operation not authorized"; }
-
- IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
- .getInstance(IForwardingRulesManager.class, "default", this);
-***************
-*** 235,248 ****
- *
- * @param level
- */
-- private boolean authorize(UserLevel level) {
- IUserManager userManager = (IUserManager) ServiceHelper
- .getGlobalInstance(IUserManager.class, this);
- if (userManager == null) {
- return false;
- }
-
-- String username = SecurityContextHolder.getContext().getAuthentication().getName();
- UserLevel userLevel = userManager.getUserLevel(username);
- if (userLevel.toNumber() <= level.toNumber()) {
- return true;
---- 236,249 ----
- *
- * @param level
- */
-+ private boolean authorize(UserLevel level, HttpServletRequest request) {
- IUserManager userManager = (IUserManager) ServiceHelper
- .getGlobalInstance(IUserManager.class, this);
- if (userManager == null) {
- return false;
- }
-
-+ String username = request.getUserPrincipal().getName();
- UserLevel userLevel = userManager.getUserLevel(username);
- if (userLevel.toNumber() <= level.toNumber()) {
- return true;
<!-- #menu -->
<div id="menu" class="navbar navbar-fixed-top">
<div class="navbar-inner row-fluid">
- <div class="span10">
+ <div class="span9">
<a class="brand" href="/" title="${version}">${name}</a>
<ul class="nav nav-tabs">
</ul>
</div>
- <div class="span2">
+ <div class="span3">
<div id="toolbar" class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<div class="icon-user"></div> ${username} <span class="caret"></span>
</body>
-</html>
\ No newline at end of file
+</html>
if (body.length == 0 && !(typeof thead === 'undefined')) {
var $tr = $(document.createElement('tr'));
var $td = $(document.createElement('td'));
- $td.attr("colspan", thead.length);
- $td.text("No data available");
- $td.addClass("empty");
+ $td.attr('colspan', thead.length);
+ $td.text('No data available');
+ $td.addClass('empty');
$tr.append($td);
$tbody.append($tr);
return $tbody;
// else, populate as usual
$(body).each(function(index, value) {
var $tr = $(document.createElement('tr'));
- // data-id
- if (value['id'] != undefined) {
- $tr.attr('data-id', value['id']);
- }
- // add classes
- $(value["type"]).each(function(index, value) {
- $tr.addClass(value);
- });
- // add entries
- $(value["entry"]).each(function(index, value) {
- var $td = $(document.createElement('td'));
- $td.append(value);
- $tr.append($td);
+ $.each(value, function(key, value) {
+ if (key == 'type') {
+ // add classes
+ $(value).each(function(index, value) {
+ $tr.addClass(value);
+ });
+ } else if (key == 'entry') {
+ // add entries
+ $(value).each(function(index, value) {
+ var $td = $(document.createElement('td'));
+ $td.append(value);
+ $tr.append($td);
+ });
+ } else {
+ // data field
+ $tr.attr('data-' + key, value);
+ }
+ $tbody.append($tr);
});
- $tbody.append($tr);
});
return $tbody;
}
one.lib.registry.alert = setTimeout(function() {
$("#alert").slideUp();
}, 8000);
-}
\ No newline at end of file
+}