From 3192eba4c145930a1f54950966b9b451ebb12b51 Mon Sep 17 00:00:00 2001 From: Shigeru Yasuda Date: Wed, 19 Nov 2014 19:44:23 +0900 Subject: [PATCH] Bug 2158: Handle out-of-order inventory notification. MD-SAL notifications are delivered on multiple threads. So VTN Manager should not expect order of inventory notifications. Change-Id: I9a23203b085ab114b8de11c6584903ab3850755e Signed-off-by: Shigeru Yasuda --- .../vtn/manager/internal/VTNManagerImpl.java | 201 +++++++++++------- .../internal/VTNManagerImplWithNodesTest.java | 149 ++++++++----- 2 files changed, 223 insertions(+), 127 deletions(-) diff --git a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java index d2bfd5ef..670e0ba5 100644 --- a/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java +++ b/manager/implementation/src/main/java/org/opendaylight/vtn/manager/internal/VTNManagerImpl.java @@ -290,12 +290,11 @@ public class VTNManagerImpl * Keeps internal ports as map key. * *

- * This map is used as {@code Set}. So we use - * {@code VNodeState} enum as value in order to reduce memory footprint - * and traffic between cluster nodes. + * This map keeps pairs of {@link NodeConnector} instances corresponding + * to switch ports connected each other. *

*/ - private ConcurrentMap islDB; + private ConcurrentMap islDB; /** * Keeps flow conditions configured in this container. @@ -861,7 +860,7 @@ public class VTNManagerImpl stateDB = new ConcurrentHashMap(); nodeDB = new ConcurrentHashMap(); portDB = new ConcurrentHashMap(); - islDB = new ConcurrentHashMap(); + islDB = new ConcurrentHashMap(); clusterEvent = new ConcurrentHashMap(); flowDB = new ConcurrentHashMap(); @@ -893,7 +892,7 @@ public class VTNManagerImpl getCache(cluster, CACHE_NODES); portDB = (ConcurrentMap) getCache(cluster, CACHE_PORTS); - islDB = (ConcurrentMap) + islDB = (ConcurrentMap) getCache(cluster, CACHE_ISL); flowCondDB = (ConcurrentMap) getCache(cluster, CACHE_FLOWCOND); @@ -1246,7 +1245,6 @@ public class VTNManagerImpl PortProperty pp = new PortProperty(propMap); PortProperty old = portDB.putIfAbsent(nc, pp); if (old == null) { - addNode(nc.getNode(), false); LOG.info("{}: addPort: New port: port={}, prop={}", containerName, nc, pp); return UpdateType.ADDED; @@ -1348,18 +1346,25 @@ public class VTNManagerImpl * {@code -1} is returned if the given edge is invalid. */ private int addISL(Edge edge, Map islMap) { + // Ensure both ports are valid. NodeConnector head = edge.getHeadNodeConnector(); NodeConnector tail = edge.getTailNodeConnector(); - if (portDB.containsKey(head) && portDB.containsKey(tail)) { - boolean h = addISLPort(head, islMap); - boolean t = addISLPort(tail, islMap); - return (h || t) ? 1 : 0; - } else if (LOG.isDebugEnabled()) { - LOG.debug("{}: addISL: Ignore invalid edge: {}", - containerName, edge); + + try { + NodeUtils.checkNodeConnector(head); + NodeUtils.checkNodeConnector(tail); + } catch (VTNException e) { + if (LOG.isDebugEnabled()) { + LOG.debug("{}: addISL: Ignore invalid edge {}: {}", + containerName, edge, e); + } + + return -1; } - return -1; + boolean h = addISLPort(head, tail, islMap); + boolean t = addISLPort(tail, head, islMap); + return (h || t) ? 1 : 0; } /** @@ -1396,7 +1401,10 @@ public class VTNManagerImpl * {@link #rwLock}. *

* - * @param nc A node connector. + * @param nc A {@link NodeConnector} instance corresponding to the + * target switch port. + * @param peer A {@link NodeConnector} instance corresponding to the + * switch port connected to {@link nc}. * @param islMap If a non-{@code null} value is specified, the specified * port is put to the given map only if the port was * actually added to the ISL map. @@ -1404,19 +1412,19 @@ public class VTNManagerImpl * actually added. {@code false} is returned if the given node * connector exists in the inter switch link map. */ - private boolean addISLPort(NodeConnector nc, + private boolean addISLPort(NodeConnector nc, NodeConnector peer, Map islMap) { - if (islDB.putIfAbsent(nc, VNodeState.UP) == null) { + if (islDB.putIfAbsent(nc, peer) == null) { if (islMap != null) { islMap.put(nc, Boolean.TRUE); } - LOG.info("{}: addISLPort: New ISL port {}", - containerName, nc); + LOG.info("{}: addISLPort: New ISL port {} <-> {}", + containerName, nc, peer); return true; } - if (LOG.isDebugEnabled()) { - LOG.debug("{}: addISLPort: Ignore existing port {}", + if (LOG.isTraceEnabled()) { + LOG.trace("{}: addISLPort: Ignore existing port {}", containerName, nc); } return false; @@ -1440,19 +1448,47 @@ public class VTNManagerImpl */ private boolean removeISLPort(NodeConnector nc, Map islMap) { - if (islDB.remove(nc) != null) { + NodeConnector port = nc; + boolean removed = false; + while (true) { + NodeConnector peer = islDB.remove(port); + if (peer == null) { + if (LOG.isDebugEnabled()) { + LOG.debug("{}: removeISLPort: Ignore unknown port {}", + containerName, port); + } + break; + } + + removed = true; if (islMap != null) { - islMap.put(nc, Boolean.FALSE); + islMap.put(port, Boolean.FALSE); } - LOG.info("{}: removeISLPort: Removed {}", containerName, nc); - return true; + LOG.info("{}: removeISLPort: Removed {} <-> {}", + containerName, port, peer); + port = peer; } - if (LOG.isDebugEnabled()) { - LOG.debug("{}: removeISLPort: Ignore unknown port {}", - containerName, nc); - } - return false; + return removed; + } + + /** + * Determine whether the given node connector is associated with the + * physical switch port at the edge of the SDN network. + * + *

+ * Note that this method does not check whether the given switch port + * is managed by the controller or not. + *

+ * + * @param nc A node connector. + * @return {@code true} is returned only if the given node connector + * is associated with the physical switch port at the edge of + * the SDN network. + */ + private boolean isEdgePortImpl(NodeConnector nc) { + NodeConnector peer = islDB.get(nc); + return (peer == null || !exists(peer)); } /** @@ -2286,7 +2322,7 @@ public class VTNManagerImpl * the SDN network. */ public boolean isEdgePort(NodeConnector nc) { - return (portDB.containsKey(nc) && !islDB.containsKey(nc)); + return (exists(nc) && isEdgePortImpl(nc)); } /** @@ -2318,7 +2354,8 @@ public class VTNManagerImpl * Otherwise {@code false} is returned. */ public boolean exists(NodeConnector port) { - return portDB.containsKey(port); + return (nodeDB.containsKey(port.getNode()) && + portDB.containsKey(port)); } /** @@ -2333,9 +2370,11 @@ public class VTNManagerImpl public void collectUpEdgePorts(Set portSet) { for (Map.Entry entry: portDB.entrySet()) { NodeConnector port = entry.getKey(); - PortProperty pp = entry.getValue(); - if (pp.isEnabled() && !islDB.containsKey(port)) { - portSet.add(port); + if (nodeDB.containsKey(port.getNode())) { + PortProperty pp = entry.getValue(); + if (pp.isEnabled() && isEdgePortImpl(port)) { + portSet.add(port); + } } } } @@ -2369,10 +2408,12 @@ public class VTNManagerImpl for (Map.Entry entry: portDB.entrySet()) { NodeConnector port = entry.getKey(); - PortProperty pp = entry.getValue(); - if (pp.isEnabled() && !islDB.containsKey(port) && - filter.accept(port, pp)) { - portSet.add(port); + if (nodeDB.containsKey(port.getNode())) { + PortProperty pp = entry.getValue(); + if (pp.isEnabled() && isEdgePortImpl(port) && + filter.accept(port, pp)) { + portSet.add(port); + } } } } @@ -2392,9 +2433,9 @@ public class VTNManagerImpl public boolean hasEdgePort(Node node) { for (Map.Entry entry: portDB.entrySet()) { NodeConnector port = entry.getKey(); - if (port.getNode().equals(node)) { + if (nodeDB.containsKey(node) && port.getNode().equals(node)) { PortProperty pp = entry.getValue(); - if (pp.isEnabled() && !islDB.containsKey(port)) { + if (pp.isEnabled() && isEdgePortImpl(port)) { return true; } } @@ -2411,8 +2452,12 @@ public class VTNManagerImpl * is enabled. Otherwise {@code false} is returned. */ public boolean isEnabled(NodeConnector port) { - PortProperty pp = portDB.get(port); - return (pp != null && pp.isEnabled()); + if (nodeDB.containsKey(port.getNode())) { + PortProperty pp = portDB.get(port); + return (pp != null && pp.isEnabled()); + } + + return false; } /** @@ -2423,7 +2468,7 @@ public class VTNManagerImpl * property is returned. {@code null} is returned if not found. */ public PortProperty getPortProperty(NodeConnector nc) { - return portDB.get(nc); + return (nodeDB.containsKey(nc.getNode())) ? portDB.get(nc) : null; } /** @@ -2436,8 +2481,12 @@ public class VTNManagerImpl * determined. */ public String getPortName(NodeConnector nc) { - PortProperty prop = portDB.get(nc); - return (prop == null) ? null : prop.getName(); + if (nodeDB.containsKey(nc.getNode())) { + PortProperty prop = portDB.get(nc); + return (prop == null) ? null : prop.getName(); + } + + return null; } /** @@ -5783,6 +5832,12 @@ public class VTNManagerImpl return false; } + if (!exists(nc)) { + LOG.debug("{}: probeHost: Ignore request for {}: Unknown port {}", + containerName, host, nc); + return false; + } + // Create an unicast ARP request. InetAddress target = host.getNetworkAddress(); byte[] dst = host.getDataLayerAddressBytes(); @@ -5804,7 +5859,7 @@ public class VTNManagerImpl Lock rdlock = rwLock.readLock(); rdlock.lock(); try { - if (islDB.containsKey(nc)) { + if (!isEdgePortImpl(nc)) { LOG.debug("{}: probeHost: Ignore request for {}: " + "Internal port", containerName, host); return false; @@ -7377,33 +7432,14 @@ public class VTNManagerImpl @Override public void notifyNode(Node node, UpdateType type, Map propMap) { - if (type == UpdateType.CHANGED) { - // Nothing to do. - return; - } - // Acquire writer lock because this operation may change existing // virtual network mapping. Lock wrlock = rwLock.writeLock(); + UpdateType utype = type; wrlock.lock(); try { // Maintain the node DB. - if (type == UpdateType.ADDED) { - if (connectionManager.getLocalityStatus(node) == - ConnectionLocality.LOCAL) { - // Remove all VTN flows related to this node because - // all flow entries in this node should be removed by - // protocol plugin. - for (VTNFlowDatabase fdb: vtnFlowMap.values()) { - fdb.removeFlows(this, node); - } - } - - if (!addNode(node)) { - return; - } - } else { - assert type == UpdateType.REMOVED; + if (type == UpdateType.REMOVED) { if (!removeNode(node)) { return; } @@ -7418,10 +7454,25 @@ public class VTNManagerImpl for (MacAddressTable table: macTableMap.values()) { table.flush(node); } + } else { + if (connectionManager.getLocalityStatus(node) == + ConnectionLocality.LOCAL) { + // Remove all VTN flows related to this node because + // all flow entries in this node should be removed by + // protocol plugin. + for (VTNFlowDatabase fdb: vtnFlowMap.values()) { + fdb.removeFlows(this, node); + } + } + + if (!addNode(node)) { + return; + } + utype = UpdateType.ADDED; } for (VTenantImpl vtn: tenantDB.values()) { - vtn.notifyNode(this, node, type); + vtn.notifyNode(this, node, utype); } } finally { unlock(wrlock); @@ -7446,21 +7497,19 @@ public class VTNManagerImpl wrlock.lock(); try { // Maintain the port DB. + VNodeState pstate; if (type == UpdateType.REMOVED) { if (!removePort(nc)) { return; } + + pstate = VNodeState.UNKNOWN; } else { utype = addPort(nc, propMap); if (utype == null) { return; } - } - VNodeState pstate; - if (type == UpdateType.REMOVED) { - pstate = VNodeState.UNKNOWN; - } else { // Determine whether the port is up or not. pstate = (isEnabled(nc)) ? VNodeState.UP : VNodeState.DOWN; } @@ -7719,7 +7768,7 @@ public class VTNManagerImpl NodeUtils.checkNodeType(node.getType()); NodeUtils.checkNodeConnectorType(nc.getType()); - if (islDB.containsKey(nc)) { + if (!isEdgePortImpl(nc)) { LOG.debug("{}: Ignore packet from internal node connector: {}", containerName, nc); if (connectionManager.getLocalityStatus(node) == diff --git a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/VTNManagerImplWithNodesTest.java b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/VTNManagerImplWithNodesTest.java index 607a9338..9432d861 100644 --- a/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/VTNManagerImplWithNodesTest.java +++ b/manager/implementation/src/test/java/org/opendaylight/vtn/manager/internal/VTNManagerImplWithNodesTest.java @@ -951,7 +951,8 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { mgr.initISL(); Set existNodeConnector = new HashSet(); - Set existISL = new HashSet(); + Map existISL = + new HashMap(); List addTopoList = new ArrayList(); getInventoryNodeAndPortData(mgr, existNodeConnector, existISL, addTopoList); @@ -964,10 +965,12 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { Map propMap = swMgr.getNodeConnectorProps(nc); mgr.notifyNodeConnector(nc, UpdateType.REMOVED, propMap); - int expectedNumISL = existISL.contains(nc) - ? existISL.size() - 1 : existISL.size(); + int expectedNumISL = + existISL.size() - getRemovedLinkSize(existISL, nc); checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size() - 1, expectedNumISL); + assertTrue(mgr.exists(nc.getNode())); + assertFalse(mgr.exists(nc)); // remove same port again. status is not changed. mgr.notifyNodeConnector(nc, UpdateType.REMOVED, propMap); @@ -977,8 +980,10 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { mgr.notifyNodeConnector(nc, UpdateType.ADDED, propMap); checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), expectedNumISL); + assertTrue(mgr.exists(nc.getNode())); + assertTrue(mgr.exists(nc)); - if (existISL.contains(nc)) { + if (existISL.containsKey(nc)) { // edge information isn't updated by invoking notifyNodeConnector() // until edgeUpdate() is invoked. mgr.edgeUpdate(addTopoList); @@ -996,39 +1001,44 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { existNodeConnector.size(), existISL.size()); } - // add and remove not existing node connector. - // If added existing node connector , it is added to DB. + // When a node connector in unknown node is added, node connector + // should be added but node. Node node10 = NodeCreator.createOFNode(Long.valueOf("10")); NodeConnector nc = NodeConnectorCreator .createOFNodeConnector(Short.valueOf("99"), node10); Map propMap = new HashMap(); mgr.notifyNodeConnector(nc, UpdateType.ADDED, propMap); - checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size() + 1, + checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size() + 1, existISL.size()); + // exists(NodeConnector) should return false if the node is not added. + assertFalse(mgr.exists(node10)); + assertFalse(mgr.exists(nc)); + mgr.notifyNodeConnector(nc, UpdateType.CHANGED, propMap); - checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size() + 1, + checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size() + 1, existISL.size()); + assertFalse(mgr.exists(node10)); + assertFalse(mgr.exists(nc)); // nodeDB isn't updated when notifyNodeConnector() invoked with // UpdateType.REMOVED. mgr.notifyNodeConnector(nc, UpdateType.REMOVED, propMap); - checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size() + 1, + checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), existISL.size()); - // nodeDB isn't updated until notifyNode() received(). mgr.notifyNode(node10, UpdateType.REMOVED, propMap); checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), existISL.size()); // in case propMap == null mgr.notifyNodeConnector(nc, UpdateType.ADDED, null); - checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size() + 1, + checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size() + 1, existISL.size()); mgr.notifyNodeConnector(nc, UpdateType.REMOVED, null); - checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size() + 1, + checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), existISL.size()); mgr.notifyNode(node10, UpdateType.REMOVED, null); @@ -1136,7 +1146,8 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { mgr.initISL(); Set existNodeConnector = new HashSet(); - Set existISL = new HashSet(); + Map existISL = + new HashMap(); List addTopoList = new ArrayList(); getInventoryNodeAndPortData(mgr, existNodeConnector, existISL, addTopoList); @@ -1159,13 +1170,19 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { getInventoryNodeAndPortData(mgr, existNodeConnector, existISL, addTopoList); + int removed = 0; for (Node node : swMgr.getNodes()) { mgr.initInventory(); mgr.initISL(); - int expectedNumISL = 1; - if (mode == 3) { - expectedNumISL = (node.equals(node0)) ? 2 : 3; + // If test mode is 3, node0 is linked with both node1 and + // node2. So all inter-switch links will be removed when node0 + // is removed. + int expectedNumISL; + if (mode == 2 || node.equals(node0)) { + expectedNumISL = 0; + } else { + expectedNumISL = 2; } Map propMap = swMgr.getNodeProps(node); @@ -1180,11 +1197,6 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { existNodeConnector.size() - swMgr.getNodeConnectors(node).size(), expectedNumISL); - mgr.notifyNode(node, UpdateType.CHANGED, propMap); - checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size() - 1, - existNodeConnector.size() - swMgr.getNodeConnectors(node).size(), - expectedNumISL); - // node connectors associated with specified node // are removed by invoking notifyNode(). // But these aren't added by invoking notifyNode(). @@ -1272,7 +1284,8 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { mgr.initISL(); Set existNodeConnector = new HashSet(); - Set existISL = new HashSet(); + Map existISL = + new HashMap(); getInventoryNodeAndPortData(mgr, existNodeConnector, existISL, null); checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), @@ -1371,6 +1384,13 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { NodeConnector head = NodeConnectorCreator .createOFNodeConnector(Short.valueOf(portHead), nodeHead); + boolean tailExists = !(nodeTail.equals(node100) || + portTail == 99); + boolean headExists = !(nodeHead.equals(node100) || + portHead == 99); + assertEquals(tailExists, mgr.exists(tail)); + assertEquals(headExists, mgr.exists(head)); + Edge newEdge = null; try { newEdge = new Edge(tail, head); @@ -1384,20 +1404,16 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { addTopoList.add(update); mgr.edgeUpdate(addTopoList); - if (nodeTail.equals(node100) || nodeHead.equals(node100) - || portTail == 99 || portHead == 99) { - // if tail or head is not existing NodeConnector - // islDB isn't updated. - checkNodeDBAndPortDBAndIslDB(cs, - swMgr.getNodes().size(), - existNodeConnector.size(), - existISL.size()); - } else { - checkNodeDBAndPortDBAndIslDB(cs, - swMgr.getNodes().size(), - existNodeConnector.size(), - existISL.size() + 2); - } + + // ISL DB should be updated even if edge contains + // unknown port. + checkNodeDBAndPortDBAndIslDB( + cs, swMgr.getNodes().size(), + existNodeConnector.size(), existISL.size() + 2); + boolean tailEdge = (tailExists && !headExists); + boolean headEdge = (headExists && !tailExists); + assertEquals(tailEdge, mgr.isEdgePort(tail)); + assertEquals(headEdge, mgr.isEdgePort(head)); update = new TopoEdgeUpdate(newEdge, null, UpdateType.REMOVED); @@ -1407,6 +1423,9 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { mgr.edgeUpdate(removeTopoList); checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), existISL.size()); + + assertEquals(tailEdge, mgr.isEdgePort(tail)); + assertEquals(headEdge, mgr.isEdgePort(head)); } } } @@ -1430,7 +1449,9 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { mgr.edgeUpdate(addTopoList); checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), - existISL.size()); + existISL.size() + 2); + assertFalse(mgr.isEdgePort(tail)); + assertFalse(mgr.isEdgePort(head)); update = new TopoEdgeUpdate(newEdge, null, UpdateType.REMOVED); removeTopoList.clear(); @@ -1440,6 +1461,8 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { checkNodeDBAndPortDBAndIslDB(cs, swMgr.getNodes().size(), existNodeConnector.size(), existISL.size()); + assertFalse(mgr.isEdgePort(tail)); + assertFalse(mgr.isEdgePort(head)); // start with invalid topology. // (topologyManager has edges associated with not existing Node.) @@ -1454,7 +1477,7 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { vtnMgr.setSwitchManager(stubObj); vtnMgr.setTopologyManager(stubNew); startVTNManager(c); - assertEquals(2, cs.getCache(CACHE_ISL).size()); + assertEquals(4, cs.getCache(CACHE_ISL).size()); } /** @@ -1465,15 +1488,15 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { * @param mgr VTNManager service. * @param existNodeConnector A List of {@link NodeConnector} which is set * existing Nodeconnectors. - * @param existISL A List of {@link NodeConnector} which is set - * existing ISLs. + * @param existISL A map of {@link NodeConnector} which + * contains internal links. * @param addTopoList A List of {@link TopoEdgeUpdate} which is set * {@link TopoEdgeUpdate} of existing Edges. */ - private void getInventoryNodeAndPortData(VTNManagerImpl mgr, - Set existNodeConnector, - Set existISL, - List addTopoList) { + private void getInventoryNodeAndPortData( + VTNManagerImpl mgr, Set existNodeConnector, + Map existISL, + List addTopoList) { ISwitchManager swMgr = mgr.getSwitchManager(); ITopologyManager topoMgr = mgr.getTopologyManager(); for (Node node : swMgr.getNodes()) { @@ -1481,8 +1504,10 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { } for (Edge edge : topoMgr.getEdges().keySet()) { - existISL.add(edge.getHeadNodeConnector()); - existISL.add(edge.getTailNodeConnector()); + NodeConnector head = edge.getHeadNodeConnector(); + NodeConnector tail = edge.getTailNodeConnector(); + existISL.put(head, tail); + existISL.put(tail, head); if (addTopoList != null) { TopoEdgeUpdate update = new TopoEdgeUpdate(edge, null, @@ -1512,10 +1537,8 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { cs.getCache(CACHE_PORTS); List portMapList = new ArrayList(portMap.keySet()); - ConcurrentMap islMap = - (ConcurrentMap)cs.getCache(CACHE_ISL); - List islMapList = - new ArrayList(islMap.keySet()); + ConcurrentMap islMap = + (ConcurrentMap)cs.getCache(CACHE_ISL); if (nodeDBSize >= 0) { assertEquals(nodeDBSize, nodeMapList.size()); @@ -1524,7 +1547,7 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { assertEquals(portDBSize, portMapList.size()); } if (islDBSize >= 0) { - assertEquals(islDBSize, islMapList.size()); + assertEquals(islDBSize, islMap.size()); } } @@ -5055,4 +5078,28 @@ public class VTNManagerImplWithNodesTest extends VTNManagerImplTestCommon { assertEquals(StatusCode.SUCCESS, st.getCode()); } } + + /** + * Return the number of inter-switch links to be removed when the given + * node is removed. + * + * @param map A map that contains inter-switch links. + * @param nc A node connector to be removed. + * @return The number of inter-switch links to be removed. + */ + private int getRemovedLinkSize(Map map, + NodeConnector nc) { + Set removed = new HashSet(); + NodeConnector port = nc; + do { + NodeConnector peer = map.get(port); + if (peer == null || !removed.add(port)) { + break; + } + + port = peer; + } while (true); + + return removed.size(); + } } -- 2.36.6