2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.protocol_plugin.openflow.internal;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
18 import java.util.Timer;
19 import java.util.TimerTask;
20 import java.util.concurrent.BlockingQueue;
21 import java.util.concurrent.ConcurrentHashMap;
22 import java.util.concurrent.ConcurrentMap;
23 import java.util.concurrent.CopyOnWriteArrayList;
24 import java.util.concurrent.LinkedBlockingQueue;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.apache.commons.lang3.tuple.Pair;
28 import org.eclipse.osgi.framework.console.CommandInterpreter;
29 import org.eclipse.osgi.framework.console.CommandProvider;
30 import org.opendaylight.controller.protocol_plugin.openflow.IDiscoveryListener;
31 import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExternalListener;
32 import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsManager;
33 import org.opendaylight.controller.protocol_plugin.openflow.IRefreshInternalProvider;
34 import org.opendaylight.controller.protocol_plugin.openflow.ITopologyServiceShimListener;
35 import org.opendaylight.controller.sal.core.Bandwidth;
36 import org.opendaylight.controller.sal.core.Config;
37 import org.opendaylight.controller.sal.core.ContainerFlow;
38 import org.opendaylight.controller.sal.core.Edge;
39 import org.opendaylight.controller.sal.core.IContainerAware;
40 import org.opendaylight.controller.sal.core.IContainerListener;
41 import org.opendaylight.controller.sal.core.Node;
42 import org.opendaylight.controller.sal.core.NodeConnector;
43 import org.opendaylight.controller.sal.core.Property;
44 import org.opendaylight.controller.sal.core.State;
45 import org.opendaylight.controller.sal.core.UpdateType;
46 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
47 import org.opendaylight.controller.sal.utils.GlobalConstants;
48 import org.osgi.framework.BundleContext;
49 import org.osgi.framework.FrameworkUtil;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
54 * The class describes a shim layer that relays the topology events from
55 * OpenFlow core to various listeners. The notifications are filtered based on
56 * container configurations.
58 public class TopologyServiceShim implements IDiscoveryListener,
59 IContainerListener, CommandProvider, IRefreshInternalProvider,
60 IInventoryShimExternalListener, IContainerAware {
61 protected static final Logger logger = LoggerFactory
62 .getLogger(TopologyServiceShim.class);
63 private ConcurrentMap<String, ITopologyServiceShimListener> topologyServiceShimListeners = new ConcurrentHashMap<String, ITopologyServiceShimListener>();
64 private ConcurrentMap<NodeConnector, List<String>> containerMap = new ConcurrentHashMap<NodeConnector, List<String>>();
65 private ConcurrentMap<String, ConcurrentMap<NodeConnector, Pair<Edge, Set<Property>>>> edgeMap = new ConcurrentHashMap<String, ConcurrentMap<NodeConnector, Pair<Edge, Set<Property>>>>();
67 private BlockingQueue<NotifyEntry> notifyQ;
68 private Thread notifyThread;
69 private BlockingQueue<String> bulkNotifyQ;
70 private Thread ofPluginTopoBulkUpdate;
71 private volatile Boolean shuttingDown = false;
72 private IOFStatisticsManager statsMgr;
73 private Timer pollTimer;
74 private TimerTask txRatePoller;
75 private Thread bwUtilNotifyThread;
76 private BlockingQueue<UtilizationUpdate> bwUtilNotifyQ;
77 private List<NodeConnector> connectorsOverUtilized;
78 private float bwThresholdFactor = (float) 0.8; // Threshold = 80% of link
83 List<TopoEdgeUpdate> teuList;
85 public NotifyEntry(String container, TopoEdgeUpdate teu) {
86 this.container = container;
87 this.teuList = new ArrayList<TopoEdgeUpdate>();
89 this.teuList.add(teu);
93 public NotifyEntry(String container, List<TopoEdgeUpdate> teuList) {
94 this.container = container;
95 this.teuList = new ArrayList<TopoEdgeUpdate>();
96 if (teuList != null) {
97 this.teuList.addAll(teuList);
102 class TopologyNotify implements Runnable {
103 private final BlockingQueue<NotifyEntry> notifyQ;
104 private NotifyEntry entry;
105 private Map<String, List<TopoEdgeUpdate>> teuMap = new HashMap<String, List<TopoEdgeUpdate>>();
106 private List<TopoEdgeUpdate> teuList;
107 private boolean notifyListeners;
109 TopologyNotify(BlockingQueue<NotifyEntry> notifyQ) {
110 this.notifyQ = notifyQ;
118 notifyListeners = false;
119 while (!notifyQ.isEmpty()) {
120 entry = notifyQ.take();
121 teuList = teuMap.get(entry.container);
122 if (teuList == null) {
123 teuList = new ArrayList<TopoEdgeUpdate>();
125 // group all the updates together
126 teuList.addAll(entry.teuList);
127 teuMap.put(entry.container, teuList);
128 notifyListeners = true;
131 if (notifyListeners) {
132 for (String container : teuMap.keySet()) {
133 // notify the listener
134 ITopologyServiceShimListener l = topologyServiceShimListeners.get(container);
135 // container topology service may not have come up yet
137 l.edgeUpdate(teuMap.get(container));
143 } catch (InterruptedException e1) {
144 logger.trace("TopologyNotify interrupted {}",
149 } catch (Exception e2) {
150 logger.error("", e2);
156 class UtilizationUpdate {
157 NodeConnector connector;
160 UtilizationUpdate(NodeConnector connector, UpdateType type) {
161 this.connector = connector;
166 class BwUtilizationNotify implements Runnable {
167 private final BlockingQueue<UtilizationUpdate> notifyQ;
169 BwUtilizationNotify(BlockingQueue<UtilizationUpdate> notifyQ) {
170 this.notifyQ = notifyQ;
177 UtilizationUpdate update = notifyQ.take();
178 NodeConnector connector = update.connector;
179 Set<String> containerList = edgeMap.keySet();
180 for (String container : containerList) {
181 Map<NodeConnector, Pair<Edge, Set<Property>>> edgePropsMap = edgeMap
183 // the edgePropsMap for a particular container may not have
186 Pair<Edge, Set<Property>> edgeProp = edgePropsMap.get(connector);
187 if(edgeProp != null) {
188 Edge edge = edgeProp.getLeft();
189 if (edge.getTailNodeConnector().equals(connector)) {
190 ITopologyServiceShimListener topologServiceShimListener = topologyServiceShimListeners
192 if (update.type == UpdateType.ADDED) {
193 topologServiceShimListener
194 .edgeOverUtilized(edge);
196 topologServiceShimListener
197 .edgeUtilBackToNormal(edge);
202 } catch (InterruptedException e1) {
204 "Edge Bandwidth Utilization Notify Thread interrupted {}",
209 } catch (Exception e2) {
210 logger.error("", e2);
217 * Function called by the dependency manager when all the required
218 * dependencies are satisfied
222 logger.trace("Init called");
223 connectorsOverUtilized = new ArrayList<NodeConnector>();
224 notifyQ = new LinkedBlockingQueue<NotifyEntry>();
225 notifyThread = new Thread(new TopologyNotify(notifyQ));
226 bwUtilNotifyQ = new LinkedBlockingQueue<UtilizationUpdate>();
227 bwUtilNotifyThread = new Thread(new BwUtilizationNotify(bwUtilNotifyQ));
228 bulkNotifyQ = new LinkedBlockingQueue<String>();
229 ofPluginTopoBulkUpdate = new Thread(new Runnable() {
234 String containerName = bulkNotifyQ.take();
235 logger.debug("Bulk Notify container:{}", containerName);
236 TopologyBulkUpdate(containerName);
237 } catch (InterruptedException e) {
238 logger.trace("Topology Bulk update thread interrupted");
244 }, "Topology Bulk Update");
246 // Initialize node connector tx bit rate poller timer
247 pollTimer = new Timer();
248 txRatePoller = new TimerTask() {
255 registerWithOSGIConsole();
259 * Continuously polls the transmit bit rate for all the node connectors from
260 * statistics manager and trigger the warning notification upward when the
261 * transmit rate is above a threshold which is a percentage of the edge
264 protected void pollTxBitRates() {
265 Map<NodeConnector, Pair<Edge, Set<Property>>> globalContainerEdges = edgeMap
266 .get(GlobalConstants.DEFAULT.toString());
268 logger.trace("Getting out the pollTxBitRates because bundle going down");
271 if (globalContainerEdges == null) {
275 for (NodeConnector connector : globalContainerEdges.keySet()) {
276 // Skip if node connector belongs to production switch
277 if (connector.getType().equals(
278 NodeConnector.NodeConnectorIDType.PRODUCTION)) {
282 // Get edge for which this node connector is head
283 Pair<Edge, Set<Property>> props = this.edgeMap.get(
284 GlobalConstants.DEFAULT.toString()).get(connector);
285 // On switch mgr restart the props get reset
289 Set<Property> propSet = props.getRight();
290 if (propSet == null) {
295 for (Property prop : propSet) {
296 if (prop instanceof Bandwidth) {
297 bw = ((Bandwidth) prop).getValue();
302 // Skip if agent did not provide a bandwidth info for the edge
307 // Compare bandwidth usage
308 Long switchId = (Long) connector.getNode().getID();
309 Short port = (Short) connector.getID();
310 if (statsMgr != null) {
311 float rate = statsMgr.getTransmitRate(switchId, port);
312 if (rate > bwThresholdFactor * bw) {
313 if (!connectorsOverUtilized.contains(connector)) {
314 connectorsOverUtilized.add(connector);
315 this.bwUtilNotifyQ.add(new UtilizationUpdate(connector, UpdateType.ADDED));
318 if (connectorsOverUtilized.contains(connector)) {
319 connectorsOverUtilized.remove(connector);
320 this.bwUtilNotifyQ.add(new UtilizationUpdate(connector, UpdateType.REMOVED));
329 * Function called by the dependency manager when at least one dependency
330 * become unsatisfied or when the component is shutting down because for
331 * example bundle is being stopped.
335 logger.trace("DESTROY called!");
341 * Function called by dependency manager after "init ()" is called and after
342 * the services provided by the class are registered in the service registry
346 logger.trace("START called!");
347 notifyThread.start();
348 bwUtilNotifyThread.start();
349 ofPluginTopoBulkUpdate.start();
350 pollTimer.scheduleAtFixedRate(txRatePoller, 10000, 5000);
354 * Function called by the dependency manager before the services exported by
355 * the component are unregistered, this will be followed by a "destroy ()"
360 logger.trace("STOP called!");
362 notifyThread.interrupt();
363 bwUtilNotifyThread.interrupt();
364 ofPluginTopoBulkUpdate.interrupt();
368 void setTopologyServiceShimListener(Map<?, ?> props,
369 ITopologyServiceShimListener s) {
371 logger.error("Didn't receive the service properties");
374 String containerName = (String) props.get("containerName");
375 if (containerName == null) {
376 logger.error("containerName not supplied");
379 if ((this.topologyServiceShimListeners != null)
380 && !this.topologyServiceShimListeners
381 .containsKey(containerName)) {
382 this.topologyServiceShimListeners.put(containerName, s);
383 logger.trace("Added topologyServiceShimListener for container: {}",
388 void unsetTopologyServiceShimListener(Map<?, ?> props,
389 ITopologyServiceShimListener s) {
391 logger.error("Didn't receive the service properties");
394 String containerName = (String) props.get("containerName");
395 if (containerName == null) {
396 logger.error("containerName not supplied");
399 if ((this.topologyServiceShimListeners != null)
400 && this.topologyServiceShimListeners.containsKey(containerName)
401 && this.topologyServiceShimListeners.get(containerName).equals(
403 this.topologyServiceShimListeners.remove(containerName);
405 "Removed topologyServiceShimListener for container: {}",
410 void setStatisticsManager(IOFStatisticsManager s) {
414 void unsetStatisticsManager(IOFStatisticsManager s) {
415 if (this.statsMgr == s) {
416 this.statsMgr = null;
420 private void updateContainerMap(List<String> containers, NodeConnector p) {
421 if (containers.isEmpty()) {
422 // Do cleanup to reduce memory footprint if no
423 // elements to be tracked
424 this.containerMap.remove(p);
426 this.containerMap.put(p, containers);
431 * From a given edge map, retrieve the edge sourced by the port and update
432 * the local cache in the container
436 * @param nodeConnector
440 * @return the found edge
442 private Edge addEdge(String container, NodeConnector nodeConnector,
443 Map<NodeConnector, Pair<Edge, Set<Property>>> edges) {
444 logger.debug("Search edge sourced by port {} in container {}", nodeConnector, container);
446 // Retrieve the associated edge
447 Pair<Edge, Set<Property>> edgeProps = edges.get(nodeConnector);
448 if (edgeProps == null) {
449 logger.debug("edgePros is null for port {} in container {}", nodeConnector, container);
453 Edge edge = edgeProps.getLeft();
455 logger.debug("edge is null for port {} in container {}", nodeConnector, container);
459 // Make sure the peer port is in the same container
460 NodeConnector peerConnector = edge.getHeadNodeConnector();
461 List<String> containers = this.containerMap.get(peerConnector);
462 if ((containers == null) || !containers.contains(container)) {
463 logger.debug("peer port {} of edge {} is not part of the container {}", new Object[] { peerConnector, edge,
468 // Update the local cache
469 updateLocalEdgeMap(container, edge, UpdateType.ADDED, edgeProps.getRight());
470 logger.debug("Added edge {} to local cache in container {}", edge, container);
475 private void addNodeConnector(String container,
476 NodeConnector nodeConnector) {
477 // Use the global edge map for the newly added port in a container
478 Map<NodeConnector, Pair<Edge, Set<Property>>> globalEdgeMap = edgeMap.get(GlobalConstants.DEFAULT
480 if (globalEdgeMap == null) {
484 // Get the edge and update local cache in the container
486 edge1 = addEdge(container, nodeConnector, globalEdgeMap);
491 // Get the edge in reverse direction and update local cache in the container
492 NodeConnector peerConnector = edge1.getHeadNodeConnector();
493 edge2 = addEdge(container, peerConnector, globalEdgeMap);
495 // Send notification upwards in one shot
496 List<TopoEdgeUpdate> teuList = new ArrayList<TopoEdgeUpdate>();
497 teuList.add(new TopoEdgeUpdate(edge1, null, UpdateType.ADDED));
498 logger.debug("Notify edge1: {} in container {}", edge1, container);
500 teuList.add(new TopoEdgeUpdate(edge2, null, UpdateType.ADDED));
501 logger.debug("Notify edge2: {} in container {}", edge2, container);
503 notifyEdge(container, teuList);
506 private void removeNodeConnector(String container,
507 NodeConnector nodeConnector) {
508 List<TopoEdgeUpdate> teuList = new ArrayList<TopoEdgeUpdate>();
509 Map<NodeConnector, Pair<Edge, Set<Property>>> edgePropsMap = edgeMap
511 if (edgePropsMap == null) {
515 // Remove edge in one direction
516 Pair<Edge, Set<Property>> edgeProps = edgePropsMap.get(nodeConnector);
517 if (edgeProps == null) {
520 teuList.add(new TopoEdgeUpdate(edgeProps.getLeft(), null,
521 UpdateType.REMOVED));
523 // Remove edge in another direction
524 edgeProps = edgePropsMap
525 .get(edgeProps.getLeft().getHeadNodeConnector());
526 if (edgeProps == null) {
529 teuList.add(new TopoEdgeUpdate(edgeProps.getLeft(), null,
530 UpdateType.REMOVED));
532 // Update in one shot
533 notifyEdge(container, teuList);
537 * Update local cache and return true if it needs to notify upper layer
538 * Topology listeners.
541 * The network container
547 * The edge properties
548 * @return true if it needs to notify upper layer Topology listeners
550 private boolean updateLocalEdgeMap(String container, Edge edge,
551 UpdateType type, Set<Property> props) {
552 ConcurrentMap<NodeConnector, Pair<Edge, Set<Property>>> edgePropsMap = edgeMap
554 NodeConnector src = edge.getTailNodeConnector();
555 Pair<Edge, Set<Property>> edgeProps = new ImmutablePair<Edge, Set<Property>>(
562 if (edgePropsMap == null) {
563 edgePropsMap = new ConcurrentHashMap<NodeConnector, Pair<Edge, Set<Property>>>();
566 if (edgePropsMap.containsKey(src)
567 && edgePropsMap.get(src).equals(edgeProps)) {
568 // Entry already exists. No update.
575 edgePropsMap.put(src, edgeProps);
576 edgeMap.put(container, edgePropsMap);
580 if ((edgePropsMap != null) && edgePropsMap.containsKey(src)) {
581 edgePropsMap.remove(src);
582 if (edgePropsMap.isEmpty()) {
583 edgeMap.remove(container);
585 edgeMap.put(container, edgePropsMap);
592 "notifyLocalEdgeMap: invalid {} for Edge {} in container {}",
593 new Object[] { type.getName(), edge, container });
598 "notifyLocalEdgeMap: {} for Edge {} in container {}",
599 new Object[] { type.getName(), edge, container });
605 private void notifyEdge(String container, Edge edge, UpdateType type,
606 Set<Property> props) {
607 boolean notifyListeners;
609 // Update local cache
610 notifyListeners = updateLocalEdgeMap(container, edge, type, props);
612 // Prepare to update TopologyService
613 if (notifyListeners) {
614 notifyQ.add(new NotifyEntry(container, new TopoEdgeUpdate(edge, props,
616 logger.debug("notifyEdge: {} Edge {} in container {}",
617 new Object[] { type.getName(), edge, container });
621 private void notifyEdge(String container, List<TopoEdgeUpdate> etuList) {
622 if (etuList == null) {
628 List<TopoEdgeUpdate> etuNotifyList = new ArrayList<TopoEdgeUpdate>();
629 boolean notifyListeners = false, rv;
631 for (TopoEdgeUpdate etu : etuList) {
632 edge = etu.getEdge();
633 type = etu.getUpdateType();
635 // Update local cache
636 rv = updateLocalEdgeMap(container, edge, type, etu.getProperty());
638 if (!notifyListeners) {
639 notifyListeners = true;
641 etuNotifyList.add(etu);
643 "notifyEdge(TopoEdgeUpdate): {} Edge {} in container {}",
644 new Object[] { type.getName(), edge, container });
648 // Prepare to update TopologyService
649 if (notifyListeners) {
650 notifyQ.add(new NotifyEntry(container, etuNotifyList));
651 logger.debug("notifyEdge(TopoEdgeUpdate): add notifyQ");
656 public void notifyEdge(Edge edge, UpdateType type, Set<Property> props) {
657 if ((edge == null) || (type == null)) {
661 // Notify default container
662 notifyEdge(GlobalConstants.DEFAULT.toString(), edge, type, props);
664 // Notify the corresponding containers
665 List<String> containers = getEdgeContainers(edge);
666 if (containers != null) {
667 for (String container : containers) {
668 notifyEdge(container, edge, type, props);
674 * Return a list of containers the edge associated with
676 private List<String> getEdgeContainers(Edge edge) {
677 NodeConnector src = edge.getTailNodeConnector(), dst = edge
678 .getHeadNodeConnector();
680 if (!src.getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
681 /* Find the common containers for both ends */
682 List<String> srcContainers = this.containerMap.get(src), dstContainers = this.containerMap
683 .get(dst), cmnContainers = null;
684 if ((srcContainers != null) && (dstContainers != null)) {
685 cmnContainers = new ArrayList<String>(srcContainers);
686 cmnContainers.retainAll(dstContainers);
688 return cmnContainers;
691 * If the neighbor is part of a monitored production network, get
692 * the containers that the edge port belongs to
694 return this.containerMap.get(dst);
699 public void tagUpdated(String containerName, Node n, short oldTag,
700 short newTag, UpdateType t) {
704 public void containerFlowUpdated(String containerName,
705 ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) {
709 public void nodeConnectorUpdated(String containerName, NodeConnector p,
711 if (this.containerMap == null) {
712 logger.error("containerMap is NULL");
715 List<String> containers = this.containerMap.get(p);
716 if (containers == null) {
717 containers = new CopyOnWriteArrayList<String>();
721 if (!containers.contains(containerName)) {
722 containers.add(containerName);
723 updateContainerMap(containers, p);
724 addNodeConnector(containerName, p);
728 if (containers.contains(containerName)) {
729 containers.remove(containerName);
730 updateContainerMap(containers, p);
731 removeNodeConnector(containerName, p);
740 public void containerModeUpdated(UpdateType t) {
744 private void registerWithOSGIConsole() {
745 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
747 bundleContext.registerService(CommandProvider.class.getName(), this,
752 public String getHelp() {
753 StringBuffer help = new StringBuffer();
754 help.append("---Topology Service Shim---\n");
755 help.append("\t pem [container] - Print edgeMap entries");
756 help.append(" for a given container\n");
757 return help.toString();
760 public void _pem(CommandInterpreter ci) {
761 String container = ci.nextArgument();
762 if (container == null) {
763 container = GlobalConstants.DEFAULT.toString();
766 ci.println("Container: " + container);
767 ci.println(" Edge Bandwidth");
769 Map<NodeConnector, Pair<Edge, Set<Property>>> edgePropsMap = edgeMap
771 if (edgePropsMap == null) {
775 for (Pair<Edge, Set<Property>> edgeProps : edgePropsMap.values()) {
776 if (edgeProps == null) {
781 Set<Property> props = edgeProps.getRight();
783 for (Property prop : props) {
784 if (prop.getName().equals(Bandwidth.BandwidthPropName)) {
785 bw = ((Bandwidth) prop).getValue();
790 ci.println(edgeProps.getLeft() + " " + bw);
792 ci.println("Total number of Edges: " + count);
795 public void _bwfactor(CommandInterpreter ci) {
796 String factorString = ci.nextArgument();
797 if (factorString == null) {
798 ci.println("Bw threshold: " + this.bwThresholdFactor);
799 ci.println("Insert a non null bw threshold");
802 bwThresholdFactor = Float.parseFloat(factorString);
803 ci.println("New Bw threshold: " + this.bwThresholdFactor);
807 * This method will trigger topology updates to be sent toward SAL. SAL then
808 * pushes the updates to ALL the applications that have registered as
809 * listeners for this service. SAL has no way of knowing which application
810 * requested for the refresh.
812 * As an example of this case, is stopping and starting the Topology
813 * Manager. When the topology Manager is stopped, and restarted, it will no
814 * longer have the latest topology. Hence, a request is sent here.
816 * @param containerName
820 public void requestRefresh(String containerName) {
821 // wake up a bulk update thread and exit
822 // the thread will execute the bulkUpdate()
823 bulkNotifyQ.add(containerName);
827 * Retrieve the edges for a given container
829 * @param containerName
831 * @return the edges and their properties
833 private Collection<Pair<Edge, Set<Property>>> getEdgeProps(String containerName) {
834 Map<NodeConnector, Pair<Edge, Set<Property>>> edgePropMap = null;
835 edgePropMap = edgeMap.get(containerName);
836 if (edgePropMap == null) {
839 return edgePropMap.values();
843 * Reading the current topology database, the method will replay all the
844 * edge updates for the ITopologyServiceShimListener instance in the given
845 * container, which will in turn publish them toward SAL.
847 * @param containerName
850 private void TopologyBulkUpdate(String containerName) {
851 Collection<Pair<Edge, Set<Property>>> edgeProps = null;
853 logger.debug("Try bulk update for container:{}", containerName);
854 edgeProps = getEdgeProps(containerName);
855 if (edgeProps == null) {
856 logger.debug("No edges known for container:{}", containerName);
859 ITopologyServiceShimListener topologServiceShimListener = topologyServiceShimListeners
861 if (topologServiceShimListener == null) {
862 logger.debug("No topology service shim listener for container:{}",
867 List<TopoEdgeUpdate> teuList = new ArrayList<TopoEdgeUpdate>();
868 for (Pair<Edge, Set<Property>> edgeProp : edgeProps) {
869 if (edgeProp != null) {
871 teuList.add(new TopoEdgeUpdate(edgeProp.getLeft(), edgeProp
872 .getRight(), UpdateType.ADDED));
873 logger.trace("Add edge {}", edgeProp.getLeft());
877 topologServiceShimListener.edgeUpdate(teuList);
879 logger.debug("Sent {} updates", i);
883 public void updateNode(Node node, UpdateType type, Set<Property> props) {
887 public void updateNodeConnector(NodeConnector nodeConnector,
888 UpdateType type, Set<Property> props) {
889 List<String> containers = new ArrayList<String>();
890 List<String> conList = this.containerMap.get(nodeConnector);
892 containers.add(GlobalConstants.DEFAULT.toString());
893 if (conList != null) {
894 containers.addAll(conList);
905 boolean rmEdge = false;
906 for (Property prop : props) {
907 if (((prop instanceof Config) && (((Config) prop).getValue() != Config.ADMIN_UP))
908 || ((prop instanceof State) && (((State) prop)
909 .getValue() != State.EDGE_UP))) {
911 * If port admin down or link down, remove the edges
912 * associated with the port
920 for (String cName : containers) {
921 removeNodeConnector(cName, nodeConnector);
926 for (String cName : containers) {
927 removeNodeConnector(cName, nodeConnector);
936 public void containerCreate(String containerName) {
941 public void containerDestroy(String containerName) {
942 Set<NodeConnector> removeNodeConnectorSet = new HashSet<NodeConnector>();
943 for (Map.Entry<NodeConnector, List<String>> entry : containerMap.entrySet()) {
944 List<String> ncContainers = entry.getValue();
945 if (ncContainers.contains(containerName)) {
946 NodeConnector nodeConnector = entry.getKey();
947 removeNodeConnectorSet.add(nodeConnector);
950 for (NodeConnector nodeConnector : removeNodeConnectorSet) {
951 List<String> ncContainers = containerMap.get(nodeConnector);
952 ncContainers.remove(containerName);
953 if (ncContainers.isEmpty()) {
954 containerMap.remove(nodeConnector);
957 edgeMap.remove(containerName);