blob: 37b64253c294731f4206335594a9535c53928808 [file] [log] [blame]
Pavlin Radoslavov15954d42013-10-19 15:29:04 -07001package net.onrc.onos.ofcontroller.topology;
2
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08003import java.util.List;
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -08004import java.util.LinkedList;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -07005import java.util.Map;
Pavlin Radoslavovdf656d62013-10-31 17:24:32 -07006import java.util.TreeMap;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -07007
Yuta HIGUCHId8c37242014-01-07 11:51:29 -08008import net.onrc.onos.graph.DBOperation;
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -08009import net.onrc.onos.graph.IDBOperation;
10import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070011import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
12import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
13
14import org.openflow.util.HexString;
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080015import org.slf4j.Logger;
16import org.slf4j.LoggerFactory;
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070017
18import com.tinkerpop.blueprints.Direction;
19import com.tinkerpop.blueprints.Vertex;
20
21/**
22 * A class for storing Node and Link information for fast computation
23 * of shortest paths.
24 */
25class Node {
26 /**
27 * A class for storing Link information for fast computation of shortest
28 * paths.
29 */
30 class Link {
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080031 public Node me; // The node this link originates from
32 public Node neighbor; // The neighbor node on the other side
33 public int myPort; // Local port ID for the link
34 public int neighborPort; // Neighbor port ID for the link
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070035
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080036 /**
37 * Link constructor.
38 *
39 * @param me the node this link originates from.
40 * @param the neighbor node on the other side of the link.
41 * @param myPort local port ID for the link.
42 * @param neighborPort neighbor port ID for the link.
43 */
44 public Link(Node me, Node neighbor, int myPort, int neighborPort) {
45 this.me = me;
46 this.neighbor = neighbor;
47 this.myPort = myPort;
48 this.neighborPort = neighborPort;
49 }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070050 };
51
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070052 public long nodeId; // The node ID
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080053 // TODO Change type of PortNumber to Short
Pavlin Radoslavovdf656d62013-10-31 17:24:32 -070054 public TreeMap<Integer, Link> links; // The links from this node:
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080055 // (src PortNumber -> Link)
Pavlin Radoslavovdf656d62013-10-31 17:24:32 -070056 private TreeMap<Integer, Link> reverseLinksMap; // The links to this node:
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080057 // (dst PortNumber -> Link)
Pavlin Radoslavovdf656d62013-10-31 17:24:32 -070058 private TreeMap<Integer, Integer> portsMap; // The ports on this node:
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080059 // (PortNumber -> PortNumber)
Pavlin Radoslavovf9161ca2013-10-31 17:08:12 -070060 // TODO: In the future will be:
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -080061 // (PortNumber -> Port)
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070062
63 /**
64 * Node constructor.
65 *
66 * @param nodeId the node ID.
67 */
68 public Node(long nodeId) {
69 this.nodeId = nodeId;
Pavlin Radoslavovdf656d62013-10-31 17:24:32 -070070 links = new TreeMap<Integer, Link>();
71 reverseLinksMap = new TreeMap<Integer, Link>();
72 portsMap = new TreeMap<Integer, Integer>();
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070073 }
74
75 /**
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070076 * Get all ports.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070077 *
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070078 * @return all ports.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -070079 */
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070080 public Map<Integer, Integer> ports() {
81 return portsMap;
82 }
83
84 /**
85 * Get the port for a given Port ID.
86 *
87 * Note: For now the port itself is just the Port ID. In the future
88 * it might contain more information.
89 *
90 * @return the port if found, otherwise null.
91 */
92 public Integer getPort(int portId) {
Yuta HIGUCHIdbc8c442013-10-31 10:15:37 -070093 return portsMap.get(portId);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -070094 }
95
96 /**
97 * Add a port for a given Port ID.
98 *
99 * Note: For now the port itself is just the Port ID. In the future
100 * it might contain more information.
101 *
102 * @param portId the Port ID of the port to add.
103 * @return the added Port.
104 */
105 Integer addPort(int portId) {
106 Integer port = new Integer(portId);
107 portsMap.put(portId, port);
108 return port;
109 }
110
111 /**
112 * Remove a port for a given Port ID.
113 *
114 * NOTE: The outgoing and incoming links using this port are removed as
115 * well.
116 */
117 void removePort(int portId) {
118 // Remove the outgoing link
119 Link link = getLink(portId);
120 if (link != null) {
121 link.neighbor.removeReverseLink(link);
122 removeLink(portId);
123 }
124
125 // Remove the incoming link
126 Link reverseLink = reverseLinksMap.get(portId);
127 if (reverseLink != null) {
128 // NOTE: reverseLink.myPort is the neighbor's outgoing port
Pavlin Radoslavov823f3222013-11-04 21:57:31 -0800129 reverseLink.me.removeLink(reverseLink.myPort);
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700130 removeReverseLink(reverseLink);
131 }
132
133 portsMap.remove(portId);
134 }
Yuta HIGUCHI63ee5a82013-10-31 10:16:15 -0700135
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700136 /**
137 * Get a link on a port to a neighbor.
138 *
139 * @param myPortId the local port ID for the link to the neighbor.
140 * @return the link if found, otherwise null.
141 */
142 public Link getLink(int myPortId) {
143 return links.get(myPortId);
144 }
145
146 /**
147 * Add a link to a neighbor.
148 *
149 * @param myPortId the local port ID for the link to the neighbor.
150 * @param neighbor the neighbor for the link.
151 * @param neighborPortId the neighbor port ID for the link.
152 * @return the added Link.
153 */
154 public Link addLink(int myPortId, Node neighbor, int neighborPortId) {
155 Link link = new Link(this, neighbor, myPortId, neighborPortId);
156 links.put(myPortId, link);
157 neighbor.addReverseLink(link);
158 return link;
159 }
160
161 /**
162 * Add a reverse link from a neighbor.
163 *
164 * @param link the reverse link from a neighbor to add.
165 */
166 private void addReverseLink(Link link) {
167 // NOTE: link.neghborPort is my port
168 reverseLinksMap.put(link.neighborPort, link);
169 }
170
171 /**
172 * Remove a link to a neighbor.
173 *
174 * @param myPortId the local port ID for the link to the neighbor.
175 */
176 public void removeLink(int myPortId) {
177 links.remove(myPortId);
178 }
179
180 /**
181 * Remove a reverse link from a neighbor.
182 *
183 * @param link the reverse link from a neighbor to remove.
184 */
185 private void removeReverseLink(Link link) {
186 // NOTE: link.neghborPort is my port
187 reverseLinksMap.remove(link.neighborPort);
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700188 }
189};
190
191/**
192 * A class for storing topology information.
193 */
194public class Topology {
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800195 private final static Logger log = LoggerFactory.getLogger(Topology.class);
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800196
197 // flag to use optimized readFromDatabase() method.
Pavlin Radoslavov8bf09af2014-01-14 21:11:00 -0800198 private static final boolean enableOptimizedRead = true;
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800199
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700200 private Map<Long, Node> nodesMap; // The dpid->Node mapping
201
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700202 /**
203 * Default constructor.
204 */
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700205 public Topology() {
Pavlin Radoslavovdf656d62013-10-31 17:24:32 -0700206 nodesMap = new TreeMap<Long, Node>();
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700207 }
208
209 /**
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700210 * Add a topology element to the topology.
211 *
212 * @param topologyElement the topology element to add.
213 * @return true if the topology was modified, otherwise false.
214 */
215 public boolean addTopologyElement(TopologyElement topologyElement) {
216 boolean isModified = false;
217
218 switch (topologyElement.getType()) {
219 case ELEMENT_SWITCH: {
220 // Add the switch
221 Node node = getNode(topologyElement.getSwitch());
222 if (node == null) {
223 node = addNode(topologyElement.getSwitch());
224 isModified = true;
225 }
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700226 break;
227 }
228 case ELEMENT_PORT: {
229 // Add the switch
230 Node node = getNode(topologyElement.getSwitch());
231 if (node == null) {
232 node = addNode(topologyElement.getSwitch());
233 isModified = true;
234 }
235 // Add the port for the switch
236 Integer port = node.getPort(topologyElement.getSwitchPort());
237 if (port == null) {
238 node.addPort(topologyElement.getSwitchPort());
239 isModified = true;
240 }
241 break;
242 }
243 case ELEMENT_LINK: {
244 // Add the "from" switch
245 Node fromNode = getNode(topologyElement.getFromSwitch());
246 if (fromNode == null) {
247 fromNode = addNode(topologyElement.getFromSwitch());
248 isModified = true;
249 }
250 // Add the "to" switch
251 Node toNode = getNode(topologyElement.getToSwitch());
252 if (toNode == null) {
253 toNode = addNode(topologyElement.getToSwitch());
254 isModified = true;
255 }
256 // Add the "from" port
257 Integer fromPort = fromNode.getPort(topologyElement.getFromPort());
258 if (fromPort == null) {
259 fromNode.addPort(topologyElement.getFromPort());
260 isModified = true;
261 }
262 // Add the "to" port
263 Integer toPort = fromNode.getPort(topologyElement.getToPort());
264 if (toPort == null) {
265 toNode.addPort(topologyElement.getToPort());
266 isModified = true;
267 }
268 Node.Link link = fromNode.getLink(topologyElement.getFromPort());
269 if (link == null) {
270 fromNode.addLink(topologyElement.getFromPort(),
271 toNode,
272 topologyElement.getToPort());
273 isModified = true;
274 }
275
276 break;
277 }
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800278 case ELEMENT_UNKNOWN:
279 // TODO: Adding "assert(false);" here can be dangerous
280 break;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700281 }
282
283 return isModified;
284 }
285
286 /**
287 * Remove a topology element from the topology.
288 *
289 * @param topologyElement the topology element to remove.
290 * @return true if the topology was modified, otherwise false.
291 */
292 public boolean removeTopologyElement(TopologyElement topologyElement) {
293 boolean isModified = false;
294
295 switch (topologyElement.getType()) {
296 case ELEMENT_SWITCH: {
297 // Remove the switch
298 Node node = getNode(topologyElement.getSwitch());
299 if (node != null) {
300 removeNode(node);
301 isModified = true;
302 }
303 break;
304 }
305 case ELEMENT_PORT: {
306 // Find the switch
307 Node node = getNode(topologyElement.getSwitch());
308 if (node == null)
309 break;
310 // Remove the port for the switch
311 Integer port = node.getPort(topologyElement.getSwitchPort());
312 if (port != null) {
313 node.removePort(topologyElement.getSwitchPort());
314 isModified = true;
315 }
316 break;
317 }
318 case ELEMENT_LINK: {
319 // Find the "from" switch
320 Node fromNode = getNode(topologyElement.getFromSwitch());
321 if (fromNode == null)
322 break;
323 // Remove the link originating from the "from" port
324 Node.Link link = fromNode.getLink(topologyElement.getFromPort());
325 if (link != null) {
326 fromNode.removeLink(topologyElement.getFromPort());
327 isModified = true;
328 }
329 break;
330 }
Pavlin Radoslavov4839f6d2013-12-11 12:49:45 -0800331 case ELEMENT_UNKNOWN:
332 // TODO: Adding "assert(false);" here can be dangerous
333 break;
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700334 }
335
336 return isModified;
337 }
338
339 /**
340 * Get a node for a given Node ID.
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700341 *
342 * @param nodeId the Node ID to use.
343 * @return the corresponding Node if found, otherwise null.
344 */
345 Node getNode(long nodeId) {
346 return nodesMap.get(nodeId);
347 }
348
349 /**
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700350 * Add a node for a given Node ID.
351 *
352 * @param nodeId the Node ID to use.
353 * @return the added Node.
354 */
355 Node addNode(long nodeId) {
356 Node node = new Node(nodeId);
357 nodesMap.put(nodeId, node);
358 return node;
359 }
360
361 /**
362 * Remove an existing node.
363 *
364 * @param node the Node to remove.
365 */
366 void removeNode(Node node) {
367 //
368 // Remove all ports one-by-one. This operation will also remove the
369 // incoming links originating from the neighbors.
370 //
Pavlin Radoslavovcfe7b402013-10-30 19:44:22 -0700371 // NOTE: We have to extract all Port IDs in advance, otherwise we
372 // cannot loop over the Ports collection and remove entries at the
373 // same time.
374 // TODO: If there is a large number of ports, the implementation
375 // below can be sub-optimal. It should be refactored as follows:
376 // 1. Modify removePort() to perform all the cleanup, except
377 // removing the Port entry from the portsMap
378 // 2. Call portsMap.clear() at the end of this method
379 // 3. In all other methods: if removePort() is called somewhere else,
380 // add an explicit removal of the Port entry from the portsMap.
381 //
382 List<Integer> allPortIdKeys = new LinkedList<Integer>();
383 allPortIdKeys.addAll(node.ports().keySet());
384 for (Integer portId : allPortIdKeys)
Pavlin Radoslavova23e5412013-10-27 19:56:40 -0700385 node.removePort(portId);
386
387 nodesMap.remove(node.nodeId);
388 }
389
390 /**
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700391 * Read topology state from the database.
392 *
393 * @param dbHandler the Graph Database handler to use.
394 */
yoshitomob292c622013-11-23 14:35:58 -0800395 public void readFromDatabase(DBOperation dbHandler) {
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800396 if (enableOptimizedRead) {
397 readFromDatabaseBodyOptimized(dbHandler);
398 } else {
399 readFromDatabaseBody(dbHandler);
400 }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700401
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800402 }
403
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800404 private void readFromDatabaseBody(DBOperation dbHandler) {
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800405 //
406 // Fetch the relevant info from the Switch and Port vertices
407 // from the Titan Graph.
408 //
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700409
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800410 nodesMap.clear();
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800411 Iterable<ISwitchObject> activeSwitches = dbHandler.getActiveSwitches();
412 for (ISwitchObject switchObj : activeSwitches) {
413 Vertex nodeVertex = switchObj.asVertex();
414 //
415 // The Switch info
416 //
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800417 Object obj = nodeVertex.getProperty("dpid");
418 if (obj == null)
419 continue; // Ignore vertices with empty attributes
420 String nodeDpid = obj.toString();
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800421 long nodeId = HexString.toLong(nodeDpid);
422 Node me = nodesMap.get(nodeId);
423 if (me == null)
424 me = addNode(nodeId);
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700425
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800426 //
427 // The local Port info
428 //
429 for (Vertex myPortVertex : nodeVertex.getVertices(Direction.OUT, "on")) {
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800430 obj = myPortVertex.getProperty("state");
431 if (obj == null)
432 continue; // Ignore vertices with empty attributes
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800433 // Ignore inactive ports
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800434 if (! obj.toString().equals("ACTIVE"))
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800435 continue;
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800436
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800437 int myPort = 0;
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800438 obj = myPortVertex.getProperty("number");
439 if (obj == null)
440 continue; // Ignore vertices with empty attributes
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800441 if (obj instanceof Short) {
442 myPort = (Short)obj;
443 } else if (obj instanceof Integer) {
444 myPort = (Integer)obj;
445 }
446 me.addPort(myPort);
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800447
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800448 for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800449 obj = neighborPortVertex.getProperty("state");
450 if (obj == null)
451 continue; // Ignore vertices with empty attributes
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800452 // Ignore inactive ports
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800453 if (! obj.toString().equals("ACTIVE")) {
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800454 continue;
455 }
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800456
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800457 int neighborPort = 0;
458 obj = neighborPortVertex.getProperty("number");
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800459 if (obj == null)
460 continue; // Ignore vertices with empty attributes
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800461 if (obj instanceof Short) {
462 neighborPort = (Short)obj;
463 } else if (obj instanceof Integer) {
464 neighborPort = (Integer)obj;
465 }
466 //
467 // The neighbor Switch info
468 //
469 for (Vertex neighborVertex : neighborPortVertex.getVertices(Direction.IN, "on")) {
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800470 obj = neighborVertex.getProperty("state");
471 if (obj == null)
472 continue; // Ignore vertices with empty attributes
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800473 // Ignore inactive switches
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800474 String state = obj.toString();
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800475 if (! state.equals(SwitchState.ACTIVE.toString()))
476 continue;
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800477
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800478 obj = neighborVertex.getProperty("dpid");
479 if (obj == null)
480 continue; // Ignore vertices with empty attributes
481 String neighborDpid = obj.toString();
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800482 long neighborId = HexString.toLong(neighborDpid);
483 Node neighbor = nodesMap.get(neighborId);
484 if (neighbor == null)
485 neighbor = addNode(neighborId);
486 neighbor.addPort(neighborPort);
487 me.addLink(myPort, neighbor, neighborPort);
488 }
489 }
490 }
Naoki Shiota0abe38d2014-01-07 15:31:22 -0800491 }
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800492 dbHandler.commit();
Yuta HIGUCHI2cef9ba2014-01-09 19:33:22 -0800493 }
494
Yuta HIGUCHI337e46d2014-01-10 22:49:27 -0800495 private void readFromDatabaseBodyOptimized(DBOperation dbHandler) {
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800496 nodesMap.clear();
497
498 // Load all switches into Map
499 Iterable<ISwitchObject> switches = dbHandler.getAllSwitches();
500 for (ISwitchObject switchObj : switches) {
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800501 String switchState = switchObj.getState();
502 if (switchState == null)
503 continue; // Ignore vertices with empty attributes
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800504 // Ignore inactive ports
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800505 if (!switchState.equals(SwitchState.ACTIVE.toString())) {
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800506 continue;
507 }
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800508
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800509 //
510 // The Switch info
511 //
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800512 Vertex nodeVertex = switchObj.asVertex();
513 Object obj = nodeVertex.getProperty("dpid");
514 if (obj == null)
515 continue; // Ignore vertices with empty attributes
516 String nodeDpid = obj.toString();
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800517 long nodeId = HexString.toLong(nodeDpid);
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800518
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800519 addNode(nodeId);
520 }
521
522 //
523 // Get All Ports
524 //
525 Iterable<IPortObject> ports = dbHandler.getAllPorts(); //TODO: Add to DB operations
526 for (IPortObject myPortObj : ports) {
527 Vertex myPortVertex = myPortObj.asVertex();
528
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800529 Object obj = myPortVertex.getProperty("state");
530 if (obj == null)
531 continue; // Ignore vertices with empty attributes
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800532 // Ignore inactive ports
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800533 if (! obj.toString().equals("ACTIVE")) {
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800534 continue;
535 }
536
537 short myPort = 0;
538 String idStr = myPortObj.getPortId();
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800539 if (idStr == null)
540 continue; // Ignore vertices with empty attributes
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800541 String[] splitter = idStr.split(IDBOperation.PORT_ID_DELIM);
542 if (splitter.length != 2) {
543 log.error("Invalid port_id : {}", idStr);
544 continue;
545 }
546 String myDpid = splitter[0];
547 myPort = Short.parseShort(splitter[1]);
548 long myId = HexString.toLong(myDpid);
549 Node me = nodesMap.get(myId);
550
551 if (me == null) {
552 // cannot proceed ports and switches are out of sync
553 //TODO: Restart the whole read
554 continue;
555 }
556
557 if (me.getPort((int)myPort) == null) {
558 me.addPort((int)myPort);
559 } else if (me.getLink((int)myPort) != null) {
560 // Link already added..probably by neighbor
561 continue;
562 }
563
564 //
565 // The neighbor Port info
566 //
567 for (Vertex neighborPortVertex : myPortVertex.getVertices(Direction.OUT, "link")) {
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800568 obj = neighborPortVertex.getProperty("state");
569 if (obj == null)
570 continue; // Ignore vertices with empty attributes
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800571 // Ignore inactive ports
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800572 if (! obj.toString().equals("ACTIVE")) {
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800573 continue;
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800574 }
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800575
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800576 int neighborPort = 0;
Pavlin Radoslavova47045f2014-02-13 18:21:31 -0800577 obj = neighborPortVertex.getProperty("port_id");
578 if (obj == null)
579 continue; // Ignore vertices with empty attributes
580 idStr = obj.toString();
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800581 splitter = idStr.split(IDBOperation.PORT_ID_DELIM);
582 if (splitter.length != 2) {
583 log.error("Invalid port_id : {}", idStr);
584 continue;
Naoki Shiotaf74d5f32014-01-09 21:29:38 -0800585 }
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800586 String neighborDpid = splitter[0];
587 neighborPort = Short.parseShort(splitter[1]);
588 long neighborId = HexString.toLong(neighborDpid);
589 Node neighbor = nodesMap.get(neighborId);
590 if (neighbor == null) {
591 continue;
592 }
593 if (neighbor.getPort(neighborPort) == null) {
594 neighbor.addPort(neighborPort);
595 }
596 me.addLink(myPort, neighbor, neighborPort);
597 }
598 }
599 dbHandler.commit();
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700600 }
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800601
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800602 // Only for debug use
603 @Override
604 public String toString() {
605 long numNodes = nodesMap.size();
606 long numLinks = 0;
607 for (Map.Entry<Long, Node> entry : nodesMap.entrySet()) {
Pavlin Radoslavov4bf118e2014-02-13 15:26:55 -0800608 Node n = entry.getValue();
609 for (Map.Entry<Integer, Node.Link> linkEntry : n.links.entrySet()) {
610 if (n.nodeId > linkEntry.getValue().neighbor.nodeId) {
611 ++numLinks;
612 }
613 }
Yuta HIGUCHId8c37242014-01-07 11:51:29 -0800614 }
615 return "Topology has " + numNodes + " Nodes and " + numLinks + " Links.";
616 }
Pavlin Radoslavov15954d42013-10-19 15:29:04 -0700617}