* Update the Topology class implementation:
- The port IDs are type "integer" instead of "short" so it will be easier
to use it for more general purpose (e.g., topologies with lots of tunnels).
- Implemented methods to get/add/remove various topology elements:
switch, port, link
- Added state to keep track of the reversed unidirectional links, so they
can be properly removed if a switch or a port is removed.
* Add a Topology instance inside the PathComputation class, and
populate it as appropriate with ENTRY_ADD/ENTRY_REMOVE topology events
from the datagrid.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/PathComputation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/PathComputation.java
index 89e8da6..cece840 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/PathComputation.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/PathComputation.java
@@ -8,6 +8,7 @@
import java.util.concurrent.LinkedBlockingQueue;
import net.onrc.onos.datagrid.IDatagridService;
+import net.onrc.onos.ofcontroller.topology.Topology;
import net.onrc.onos.ofcontroller.topology.TopologyElement;
import net.onrc.onos.ofcontroller.util.EventEntry;
import net.onrc.onos.ofcontroller.util.FlowPath;
@@ -24,6 +25,7 @@
private FlowManager flowManager; // The Flow Manager to use
private IDatagridService datagridService; // The Datagrid Service to use
+ private Topology topology; // The network topology
// The queue with Flow Path and Topology Element updates
private BlockingQueue<EventEntry<?>> networkEvents =
@@ -45,6 +47,7 @@
IDatagridService datagridService) {
this.flowManager = flowManager;
this.datagridService = datagridService;
+ this.topology = new Topology();
}
/**
@@ -117,6 +120,22 @@
if (topologyEvents.isEmpty() && flowPathEvents.isEmpty())
return; // Nothing to do
+ //
+ // Add the topology events
+ //
+ boolean isTopologyModified = false;
+ for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
+ TopologyElement topologyElement = eventEntry.eventData();
+ switch (eventEntry.eventType()) {
+ case ENTRY_ADD:
+ isTopologyModified = topology.addTopologyElement(topologyElement);
+ break;
+ case ENTRY_REMOVE:
+ isTopologyModified = topology.removeTopologyElement(topologyElement);
+ break;
+ }
+ }
+
// TODO: Implement it!
// Cleanup
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
index 1133d3d..dabe916 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/ShortestPath.java
@@ -123,7 +123,7 @@
Port outPort;
for (Node.Link link: resultPath) {
// Setup the outgoing port, and add the Flow Entry
- outPort = new Port(link.myPort);
+ outPort = new Port((short)link.myPort);
FlowEntry flowEntry = new FlowEntry();
flowEntry.setDpid(new Dpid(link.me.nodeId));
@@ -132,7 +132,7 @@
result_data_path.flowEntries().add(flowEntry);
// Setup the next incoming port
- inPort = new Port(link.neighborPort);
+ inPort = new Port((short)link.neighborPort);
}
if (resultPath.size() > 0) {
// Add the last Flow Entry
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
index a2f2c21..612b72a 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
@@ -24,18 +24,18 @@
class Link {
public Node me; // The node this link originates from
public Node neighbor; // The neighbor node on the other side
- public short myPort; // Local port number for the link
- public short neighborPort; // Neighbor port number for the link
+ public int myPort; // Local port ID for the link
+ public int neighborPort; // Neighbor port ID for the link
/**
* Link constructor.
*
* @param me the node this link originates from.
* @param the neighbor node on the other side of the link.
- * @param myPort local port number for the link.
- * @param neighborPort neighrobr port number for the link.
+ * @param myPort local port ID for the link.
+ * @param neighborPort neighbor port ID for the link.
*/
- public Link(Node me, Node neighbor, short myPort, short neighborPort) {
+ public Link(Node me, Node neighbor, int myPort, int neighborPort) {
this.me = me;
this.neighbor = neighbor;
this.myPort = myPort;
@@ -43,8 +43,10 @@
}
};
- public long nodeId; // The node ID
- public HashMap<Short, Link> links; // The links originating from this node
+ public long nodeId; // The node ID
+ public HashMap<Integer, Link> links; // The links from this node
+ private HashMap<Integer, Link> reverseLinksMap; // The links to this node
+ private HashMap<Integer, Integer> portsMap; // The ports for this node
/**
* Node constructor.
@@ -53,21 +55,124 @@
*/
public Node(long nodeId) {
this.nodeId = nodeId;
- links = new HashMap<Short, Link>();
+ links = new HashMap<Integer, Link>();
+ reverseLinksMap = new HashMap<Integer, Link>();
+ portsMap = new HashMap<Integer, Integer>();
}
/**
- * Add a neighbor.
+ * Get all ports.
*
- * A new link to the neighbor will be created.
- *
- * @param neighbor the neighbor to add.
- * @param myPort the local port number for the link to the neighbor.
- * @param neighborPort the neighbor port number for the link.
+ * @return all ports.
*/
- public void addNeighbor(Node neighbor, short myPort, short neighborPort) {
- Link link = new Link(this, neighbor, myPort, neighborPort);
- links.put(myPort, link);
+ public Map<Integer, Integer> ports() {
+ return portsMap;
+ }
+
+ /**
+ * Get the port for a given Port ID.
+ *
+ * Note: For now the port itself is just the Port ID. In the future
+ * it might contain more information.
+ *
+ * @return the port if found, otherwise null.
+ */
+ public Integer getPort(int portId) {
+ return portsMap.get(nodeId);
+ }
+
+ /**
+ * Add a port for a given Port ID.
+ *
+ * Note: For now the port itself is just the Port ID. In the future
+ * it might contain more information.
+ *
+ * @param portId the Port ID of the port to add.
+ * @return the added Port.
+ */
+ Integer addPort(int portId) {
+ Integer port = new Integer(portId);
+ portsMap.put(portId, port);
+ return port;
+ }
+
+ /**
+ * Remove a port for a given Port ID.
+ *
+ * NOTE: The outgoing and incoming links using this port are removed as
+ * well.
+ */
+ void removePort(int portId) {
+ // Remove the outgoing link
+ Link link = getLink(portId);
+ if (link != null) {
+ link.neighbor.removeReverseLink(link);
+ removeLink(portId);
+ }
+
+ // Remove the incoming link
+ Link reverseLink = reverseLinksMap.get(portId);
+ if (reverseLink != null) {
+ // NOTE: reverseLink.myPort is the neighbor's outgoing port
+ reverseLink.neighbor.removeLink(reverseLink.myPort);
+ removeReverseLink(reverseLink);
+ }
+
+ portsMap.remove(portId);
+ }
+
+ /**
+ * Get a link on a port to a neighbor.
+ *
+ * @param myPortId the local port ID for the link to the neighbor.
+ * @return the link if found, otherwise null.
+ */
+ public Link getLink(int myPortId) {
+ return links.get(myPortId);
+ }
+
+ /**
+ * Add a link to a neighbor.
+ *
+ * @param myPortId the local port ID for the link to the neighbor.
+ * @param neighbor the neighbor for the link.
+ * @param neighborPortId the neighbor port ID for the link.
+ * @return the added Link.
+ */
+ public Link addLink(int myPortId, Node neighbor, int neighborPortId) {
+ Link link = new Link(this, neighbor, myPortId, neighborPortId);
+ links.put(myPortId, link);
+ neighbor.addReverseLink(link);
+ return link;
+ }
+
+ /**
+ * Add a reverse link from a neighbor.
+ *
+ * @param link the reverse link from a neighbor to add.
+ */
+ private void addReverseLink(Link link) {
+ // NOTE: link.neghborPort is my port
+ reverseLinksMap.put(link.neighborPort, link);
+ }
+
+ /**
+ * Remove a link to a neighbor.
+ *
+ * @param myPortId the local port ID for the link to the neighbor.
+ */
+ public void removeLink(int myPortId) {
+ links.remove(myPortId);
+ }
+
+ /**
+ * Remove a reverse link from a neighbor.
+ *
+ * @param link the reverse link from a neighbor to remove.
+ */
+ private void removeReverseLink(Link link) {
+ // NOTE: link.neghborPort is my port
+ reverseLinksMap.remove(link.neighborPort);
}
};
@@ -77,12 +182,147 @@
public class Topology {
private Map<Long, Node> nodesMap; // The dpid->Node mapping
+ /**
+ * Default constructor.
+ */
public Topology() {
nodesMap = new HashMap<Long, Node>();
}
/**
- * Get a node for a give Node ID.
+ * Add a topology element to the topology.
+ *
+ * @param topologyElement the topology element to add.
+ * @return true if the topology was modified, otherwise false.
+ */
+ public boolean addTopologyElement(TopologyElement topologyElement) {
+ boolean isModified = false;
+
+ switch (topologyElement.getType()) {
+ case ELEMENT_SWITCH: {
+ // Add the switch
+ Node node = getNode(topologyElement.getSwitch());
+ if (node == null) {
+ node = addNode(topologyElement.getSwitch());
+ isModified = true;
+ }
+ // Add the ports for the switch
+ for (Integer portId : topologyElement.getSwitchPorts().values()) {
+ Integer port = node.getPort(portId);
+ if (port == null) {
+ node.addPort(portId);
+ isModified = true;
+ }
+ }
+ break;
+ }
+ case ELEMENT_PORT: {
+ // Add the switch
+ Node node = getNode(topologyElement.getSwitch());
+ if (node == null) {
+ node = addNode(topologyElement.getSwitch());
+ isModified = true;
+ }
+ // Add the port for the switch
+ Integer port = node.getPort(topologyElement.getSwitchPort());
+ if (port == null) {
+ node.addPort(topologyElement.getSwitchPort());
+ isModified = true;
+ }
+ break;
+ }
+ case ELEMENT_LINK: {
+ // Add the "from" switch
+ Node fromNode = getNode(topologyElement.getFromSwitch());
+ if (fromNode == null) {
+ fromNode = addNode(topologyElement.getFromSwitch());
+ isModified = true;
+ }
+ // Add the "to" switch
+ Node toNode = getNode(topologyElement.getToSwitch());
+ if (toNode == null) {
+ toNode = addNode(topologyElement.getToSwitch());
+ isModified = true;
+ }
+ // Add the "from" port
+ Integer fromPort = fromNode.getPort(topologyElement.getFromPort());
+ if (fromPort == null) {
+ fromNode.addPort(topologyElement.getFromPort());
+ isModified = true;
+ }
+ // Add the "to" port
+ Integer toPort = fromNode.getPort(topologyElement.getToPort());
+ if (toPort == null) {
+ toNode.addPort(topologyElement.getToPort());
+ isModified = true;
+ }
+ Node.Link link = fromNode.getLink(topologyElement.getFromPort());
+ if (link == null) {
+ fromNode.addLink(topologyElement.getFromPort(),
+ toNode,
+ topologyElement.getToPort());
+ isModified = true;
+ }
+
+ break;
+ }
+ }
+
+ return isModified;
+ }
+
+ /**
+ * Remove a topology element from the topology.
+ *
+ * @param topologyElement the topology element to remove.
+ * @return true if the topology was modified, otherwise false.
+ */
+ public boolean removeTopologyElement(TopologyElement topologyElement) {
+ boolean isModified = false;
+
+ switch (topologyElement.getType()) {
+ case ELEMENT_SWITCH: {
+ // Remove the switch
+ Node node = getNode(topologyElement.getSwitch());
+ if (node != null) {
+ removeNode(node);
+ isModified = true;
+ }
+ break;
+ }
+ case ELEMENT_PORT: {
+ // Find the switch
+ Node node = getNode(topologyElement.getSwitch());
+ if (node == null)
+ break;
+ // Remove the port for the switch
+ Integer port = node.getPort(topologyElement.getSwitchPort());
+ if (port != null) {
+ node.removePort(topologyElement.getSwitchPort());
+ isModified = true;
+ }
+ break;
+ }
+ case ELEMENT_LINK: {
+ // Find the "from" switch
+ Node fromNode = getNode(topologyElement.getFromSwitch());
+ if (fromNode == null)
+ break;
+ // Remove the link originating from the "from" port
+ Node.Link link = fromNode.getLink(topologyElement.getFromPort());
+ if (link != null) {
+ fromNode.removeLink(topologyElement.getFromPort());
+ isModified = true;
+ }
+ break;
+ }
+ }
+
+ return isModified;
+ }
+
+ /**
+ * Get a node for a given Node ID.
*
* @param nodeId the Node ID to use.
* @return the corresponding Node if found, otherwise null.
@@ -92,6 +332,34 @@
}
/**
+ * Add a node for a given Node ID.
+ *
+ * @param nodeId the Node ID to use.
+ * @return the added Node.
+ */
+ Node addNode(long nodeId) {
+ Node node = new Node(nodeId);
+ nodesMap.put(nodeId, node);
+ return node;
+ }
+
+ /**
+ * Remove an existing node.
+ *
+ * @param node the Node to remove.
+ */
+ void removeNode(Node node) {
+ //
+ // Remove all ports one-by-one. This operation will also remove the
+ // incoming links originating from the neighbors.
+ //
+ for (Integer portId : node.ports().keySet())
+ node.removePort(portId);
+
+ nodesMap.remove(node.nodeId);
+ }
+
+ /**
* Read topology state from the database.
*
* @param dbHandler the Graph Database handler to use.
@@ -110,10 +378,8 @@
String nodeDpid = nodeVertex.getProperty("dpid").toString();
long nodeId = HexString.toLong(nodeDpid);
Node me = nodesMap.get(nodeId);
- if (me == null) {
- me = new Node(nodeId);
- nodesMap.put(nodeId, me);
- }
+ if (me == null)
+ me = addNode(nodeId);
//
// The local Port info
@@ -123,13 +389,12 @@
if (! myPortVertex.getProperty("state").toString().equals("ACTIVE"))
continue;
- short myPort = 0;
+ int myPort = 0;
Object obj = myPortVertex.getProperty("number");
if (obj instanceof Short) {
myPort = (Short)obj;
} else if (obj instanceof Integer) {
- Integer int_nodeId = (Integer)obj;
- myPort = int_nodeId.shortValue();
+ myPort = (Integer)obj;
}
//
@@ -140,13 +405,12 @@
if (! neighborPortVertex.getProperty("state").toString().equals("ACTIVE"))
continue;
- short neighborPort = 0;
+ int neighborPort = 0;
obj = neighborPortVertex.getProperty("number");
if (obj instanceof Short) {
neighborPort = (Short)obj;
} else if (obj instanceof Integer) {
- Integer int_nodeId = (Integer)obj;
- neighborPort = int_nodeId.shortValue();
+ neighborPort = (Integer)obj;
}
//
// The neighbor Switch info
@@ -160,11 +424,9 @@
String neighborDpid = neighborVertex.getProperty("dpid").toString();
long neighborId = HexString.toLong(neighborDpid);
Node neighbor = nodesMap.get(neighborId);
- if (neighbor == null) {
- neighbor = new Node(neighborId);
- nodesMap.put(neighborId, neighbor);
- }
- me.addNeighbor(neighbor, myPort, neighborPort);
+ if (neighbor == null)
+ neighbor = addNode(neighborId);
+ me.addLink(myPort, neighbor, neighborPort);
}
}
}